r - 在循环中汇总并生成多个变量

标签 r loops dataframe dplyr summarize

我正在寻找一种有效的方法来操作数据框中的多个变量。现在我正在使用 dplyr,但是随着变量的增多,这会变得很麻烦。 假设我有以下数据框,其中 brd 是汽车品牌,ye 是年份,type 是汽车类型,cy 和 hp 是类型特征。

brd <-c("BMW","BMW","BMW","Volvo","Volvo", "Volvo","BMW","BMW","BMW","Volvo","Volvo","Volvo")
ye <- c(99,99,99,99,99,99,98,98,98,98,98,98)
type <- c(1,2,3,1,2,3,1,2,3,1,2,3)
cy <- c(1895,1991,1587,2435,2435,1596,1991,1588,1984,1596,1991,1588)
hp <- c(77,110,80,103,103,75,110,77,93,75,110,77)

df <- as.data.frame(brd)
df$ye <- ye
df$type <- type
df$cy <- cy
df$hp <- hp    
df
     brd ye type   cy  hp
1    BMW 99    1 1895  77
2    BMW 99    2 1991 110
3    BMW 99    3 1587  80
4  Volvo 99    1 2435 103
5  Volvo 99    2 2435 103
6  Volvo 99    3 1596  75
7    BMW 98    1 1991 110
8    BMW 98    2 1588  77
9    BMW 98    3 1984  93
10 Volvo 98    1 1596  75
11 Volvo 98    2 1991 110
12 Volvo 98    3 1588  77 

每年,我想计算同一品牌的所有其他产品的产品特征总和,并将其作为新变量添加到数据框中。现在,我正在使用 dplyr,如下所示:

library(dplyr)
df <- df %>% group_by(brd, ye) %>%
  mutate(sumall_cy = sum(cy),
         sumall_hp = sum(hp))

df <- df %>%
  mutate(sumother_cy = sumall_cy-cy,
         sumother_hp = sumall_li-hp)

这样我就得到了

      brd    ye  type    cy    hp sumall_cy sumall_hp sumother_cy sumother_hp
   <fctr> <dbl> <dbl> <dbl> <dbl>     <dbl>     <dbl>       <dbl>       <dbl>
1     BMW    99     1  1895    77      5473       267        3578         190
2     BMW    99     2  1991   110      5473       267        3482         157
3     BMW    99     3  1587    80      5473       267        3886         187
4   Volvo    99     1  2435   103      6466       281        4031         178
5   Volvo    99     2  2435   103      6466       281        4031         178
6   Volvo    99     3  1596    75      6466       281        4870         206
7     BMW    98     1  1991   110      5563       280        3572         170
8     BMW    98     2  1588    77      5563       280        3975         203
9     BMW    98     3  1984    93      5563       280        3579         187
10  Volvo    98     1  1596    75      5175       262        3579         187
11  Volvo    98     2  1991   110      5175       262        3184         152
12  Volvo    98     3  1588    77      5175       262        3587         185 

有没有更有效的方法?我正在考虑像这样的 stata 代码循环:

foreach x of varlist hp cy {

bysort ye: egen sumall_`x'= sum(`x')
gen sumother_`x'=(sumall_`x' -`x')}

如有任何建议,我们将不胜感激。

最佳答案

这是一个解决方案 non-standard evaluationgroup_by 操作只需执行一次,并且当您有更多列需要处理时也可以工作:

library(dplyr)  # 0.7.0
library(rlang)  # required for the `syms` function

varlist <- c('cy', 'hp')

# make a list of quos of opertions
ops <- sapply(syms(varlist), function(x) quo(sum(UQ(x)) - UQ(x)) )

# set new variable name
names(ops) <- paste('sumother', varlist, sep = '_')

# get results
df %>% group_by(brd, ye) %>% mutate(!!!ops) %>% ungroup()
# # A tibble: 12 x 7
#       brd    ye  type    cy    hp sumother_cy sumother_hp
#    <fctr> <dbl> <dbl> <dbl> <dbl>       <dbl>       <dbl>
#  1    BMW    99     1  1895    77        3578         190
#  2    BMW    99     2  1991   110        3482         157
#  3    BMW    99     3  1587    80        3886         187
#  4  Volvo    99     1  2435   103        4031         178
#  5  Volvo    99     2  2435   103        4031         178
#  6  Volvo    99     3  1596    75        4870         206
#  7    BMW    98     1  1991   110        3572         170
#  8    BMW    98     2  1588    77        3975         203
#  9    BMW    98     3  1984    93        3579         187
# 10  Volvo    98     1  1596    75        3579         187
# 11  Volvo    98     2  1991   110        3184         152
# 12  Volvo    98     3  1588    77        3587         185

如果我们想保留 sumall_ 列,我们可以尝试:

ops <- sapply(syms(varlist), function(x) list(quo(sum(UQ(x))), quo(sum(UQ(x)) - UQ(x))) )
names(ops) <- paste(
    rep(c('sumall', 'sumother'), length(varlist)),
    rep(varlist, each = 2), sep = '_')
df %>% group_by(brd, ye) %>% mutate(!!!ops) %>% ungroup()

# # A tibble: 12 x 9
#       brd    ye  type    cy    hp sumall_cy sumother_cy sumall_hp sumother_hp
#    <fctr> <dbl> <dbl> <dbl> <dbl>     <dbl>       <dbl>     <dbl>       <dbl>
#  1    BMW    99     1  1895    77      5473        3578       267         190
#  2    BMW    99     2  1991   110      5473        3482       267         157
#  3    BMW    99     3  1587    80      5473        3886       267         187
#  4  Volvo    99     1  2435   103      6466        4031       281         178
#  5  Volvo    99     2  2435   103      6466        4031       281         178
#  6  Volvo    99     3  1596    75      6466        4870       281         206
#  7    BMW    98     1  1991   110      5563        3572       280         170
#  8    BMW    98     2  1588    77      5563        3975       280         203
#  9    BMW    98     3  1984    93      5563        3579       280         187
# 10  Volvo    98     1  1596    75      5175        3579       262         187
# 11  Volvo    98     2  1991   110      5175        3184       262         152
# 12  Volvo    98     3  1588    77      5175        3587       262         185

关于r - 在循环中汇总并生成多个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44870255/

相关文章:

r - 在 R 中计算 AR(2) 过程的相关系数

ios - 插入数组并比较日期 Swift iOS 代码

dataframe - 在 Julia 中过滤分组的 DataFrame

python - 在 Pandas DataFrame 中使列和排序保持一致

python - 如何在 Pandas 中执行 groupby 并计算原始数据集中每行的平均值

R:如何组合具有相同 id 的数据帧的行并采用最新的非 NA 值?

r - 如何有条件地逐行比较数据并将不同的结果输出到其他列?

java - Spring thymeleaf 不会迭代列表

javascript - 使用 AngularJS 将列添加到表中

r - ifelse Action 取决于rmarkdown中的文档类型