【问题标题】:dplyr mutate new columns based on element we are iterating throughtdplyr 根据我们正在迭代的元素改变新列
【发布时间】:2020-10-21 15:12:29
【问题描述】:

我要做的是根据我们正在迭代的变量的独特元素执行一些聚合。

我能够执行我需要手动编写的内容。不过,我想概括一下这个过程,以便它可以自动执行。

library(tidyverse)


df <- 
  tibble(
  LEVEL = c('1', '1.1', '1.2', '1.1.1'),
  A = c(1, 3, 20, 10),
  B = c(100, 20, 20, 20),
  DEPTH = c(1, 2, 2, 3)
)

df %>% 
  mutate(HEAD_VOLUME = 
                  case_when(DEPTH == 1 ~ A / B,
                            TRUE ~ 0)) %>% 
  mutate(HEAD_VOLUME = 
           case_when(DEPTH != 1 ~ nth(HEAD_VOLUME, 1),
                           TRUE ~ HEAD_VOLUME)) %>% 
  mutate(DEPTH_2_VOLUME = 
          case_when(DEPTH == 2 ~ A/ B, 
                          TRUE ~ 1)) %>% 
  mutate(DEPTH_3_VOLUME = 
           case_when(DEPTH == 3 ~ A/ B, 
                     TRUE ~ 1))

现在想象 DEPTH 的数量会更大,我需要函数来解决它。 我正在考虑一个 for 循环并迭代 DEPTH 的所有唯一值。但是,我们不能(至少在 dplyr 中不能)使用paste 函数创建新列。

我正在考虑类似(伪代码):

df %>% 
  mutate(HEAD_VOLUME = 
           case_when(DEPTH == 1 ~ A / B,
                     TRUE ~ 0)) %>% 
  mutate(HEAD_VOLUME = 
           case_when(DEPTH != 1 ~ nth(HEAD_VOLUME, 1),
                     TRUE ~ HEAD_VOLUME)) %>% 
  mutate(paste('DEPTH_', i, 'VOLUME') =                # At this line i shall be second element of iter
           case_when(DEPTH == iter[i] ~ A/ B, 
                     TRUE ~ 1)) %>% 
  mutate(paste('DEPTH_', i, 'VOLUME') =                # At this line i shall be third element of iter
           case_when(DEPTH == iter[i] ~ A/ B, 
                     TRUE ~ 1))

有没有人有任何建议如何编写通用脚本/函数能够对具有不同 LEVELS 值的任何数据帧执行此聚合?

第 1 级是主要的“层次结构之上”(树根)- 第一个子子层次结构(第 2 级)。最后一个 'Sub-Sub hierarchi' 是第 3 级。但通常我们可以有三个以上的级别 - 这就是我想要自动化这个过程的原因。

头容积: 计算为 1 - 它被创建 2 次的原因,因此 TREE_HEAD(树根)计算为 1/100,因为所有子元素都来自此根。

【问题讨论】:

  • 您可以使用来自fastDummies 包的dummy_cols,如here 的回答。
  • 您能否提供更深入的解决方案?
  • 您能否解释一下您的专栏“HEAD_VOLUME”。您似乎正在创建它两次。
  • 更新了描述。

标签: r for-loop dplyr aggregation-framework purrr


【解决方案1】:

这提供了与您的代码相同的输出,并且在 DEPTH 具有更多级别的情况下也应该可以工作。它还使您免于 for 循环:

df %>%
  fastDummies::dummy_cols(select_columns = 'DEPTH') %>%
  mutate_at(vars(starts_with('DEPTH_')),funs(.*A/B)) %>%
  rename(HEAD_VOLUME=DEPTH_1) %>%
  mutate(HEAD_VOLUME=HEAD_VOLUME[1]) %>%
  mutate_at(vars(starts_with('DEPTH_')),~ifelse(.==0,1,.))

以下是输出(与您的代码相同):

  LEVEL  A   B DEPTH HEAD_VOLUME DEPTH_2 DEPTH_3
1     1  1 100     1        0.01    1.00     1.0
2   1.1  3  20     2        0.01    0.15     1.0
3   1.2 20  20     2        0.01    1.00     1.0
4 1.1.1 10  20     3        0.01    1.00     0.5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 2021-08-29
    • 2020-09-07
    • 2015-04-07
    • 1970-01-01
    相关资源
    最近更新 更多