【问题标题】:Summarizing and creating new variable according to condition in R根据R中的条件总结和创建新变量
【发布时间】:2018-04-18 20:31:57
【问题描述】:

我制作了这个虚拟数据集:

df = data.frame(Order = "Order1", 
       Condition = c("P", "A", "B", "C", "D", "E", "F"),
       Value = c(500, -10, -5,0,0, -10,0))

假设某些条件属于不同的组。

list = list( Group1 = c("A", "B"), 
      Group2 = c("C", "D"), 
      Group3 = c("E","F"))

我需要按条件对它们进行聚合,得到每个组的总和和计数。

预期输出:

Order   P   Group1 Group2 Group3 Group1n Group2n Group3n
Order1 500   -15     0      -10    2        0       1

我在想这样的事情:

df %>% group_by(Order) %>% summarise(Group1 = sum(Value[Condition == "A" | Condition == "B" ]),
                                 Group2 = sum(Value[Condition == "C" | Condition == "D" ] ),
                                 Group3 = sum(Value[Condition == "E" | Condition == "F"]),
                                 Group1n = length(Value[Condition == "A" | Condition == "B" ]),
                                 Group2n = length(Value[Condition == "C" | Condition == "D" ]),
                                 Group3n = length(Value[Condition == "E" | Condition == "F" ])) 

我的输出:

  # A tibble: 1 x 7
Order  Group1 Group2 Group3 Group1n Group2n Group3n
 <fct>   <dbl>  <dbl>  <dbl>   <dbl>   <int>   <int>
 Order1  -15.0      0  -10.0    2       2       2

但我无法正确计数。还有一种有效的方法可以让我传递列表而不是明确写 Condition ==A 或 B ...等。

谢谢

【问题讨论】:

  • 调用函数没有问题。这与这里的分组无关。
  • 我的错误 - 对不起。
  • 我不明白为什么你得到的输出是错误的。在您的示例数据框中,第 4 行是C,第 5 行是D。因此Group2 = c("C", "D") 中的行数确实是 2。为什么你期望 0?您只想计算Value 不为0 的行吗?
  • 是的,我猜它没有正确解释,但它显示在预期的输出中。欢呼

标签: r dplyr plyr


【解决方案1】:

这应该会给你你想要的:

df %>% 
  group_by(Order) %>% 
  summarise(Group1 = sum(Value[Condition == "A" | Condition == "B" ]),
            Group2 = sum(Value[Condition == "C" | Condition == "D" ] ),
            Group3 = sum(Value[Condition == "E" | Condition == "F"]),
            Group1n = sum(Condition == "A" | Condition == "B"),
            Group2n = sum(Condition == "C" | Condition == "D"),
            Group3n = sum(Condition == "E" | Condition == "F"))

您可以再清理一下。这个版本也只计算非零值(而不是每组中的所有行。)

# don't rename "list"
list_of_groups = list( Group1 = c("A", "B"), 
  Group2 = c("C", "D"), 
  Group3 = c("E","F"))
df %>% 
  group_by(Order) %>% 
  summarise(Group1 = sum(Value[Condition %in% list_of_groups$Group1]),
            Group2 = sum(Value[Condition %in% list_of_groups$Group2] ),
            Group3 = sum(Value[Condition %in% list_of_groups$Group3]),
            Group1n = sum(Condition %in% list_of_groups$Group1 & Value != 0),
            Group2n = sum(Condition %in% list_of_groups$Group2 & Value != 0),
            Group3n = sum(Condition %in% list_of_groups$Group3 & Value != 0))

利用您的群组列表 - 这样您就不必在更改群组时修复所有问题(如果相关)。

【讨论】:

  • 这是一种压缩它的好方法,但输出与我的输出相同。每个组计数 2,当它应该只是 True 值时
  • 只是为了验证,您要计算非零值吗? - 我已经编辑了底部版本以添加该标准。
【解决方案2】:

我推荐这个作为一个整洁的解决方案:

group_map = data.frame(Condition = unlist(list), Group = rep(names(list), lengths(list)), stringsAsFactors = FALSE)

result = df %>% mutate(Condition = as.character(Condition)) %>%
    inner_join(group_map) %>%
    group_by(Group, Order) %>%
    summarize(sums = sum(Value), n_nonzero = sum(Value != 0))

result
# # A tibble: 3 x 4
# # Groups:   Group [?]
#    Group  Order  sums n_nonzero
#    <chr> <fctr> <dbl>     <int>
# 1 Group1 Order1   -15         2
# 2 Group2 Order1     0         0
# 3 Group3 Order1   -10         1

如果您需要宽格式,您可以使用 data.table 重塑多个列:

library(data.table)
setDT(result)
data.table::dcast(Order ~ Group, data = result, value.var = c("sums", "n_nonzero"))
#     Order sums_Group1 sums_Group2 sums_Group3 n_nonzero_Group1 n_nonzero_Group2 n_nonzero_Group3
# 1: Order1         -15           0         -10                2                0                1

【讨论】:

  • 使用 data.table 进行有趣的重塑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-13
  • 2015-05-07
  • 1970-01-01
  • 2022-07-15
相关资源
最近更新 更多