使用分组字段过滤摘要中的原始表

时间:2019-07-15 11:14:46

标签: r dplyr

编辑。

我已重写问题,希望它更有意义。

提供此数据:

> df
  Cat1 Cat2 Q
1    A    B 1
2    A    C 1
3    B    D 1
4    B    C 1
5    C    C 1
6    C    D 1

您可以使用dplyr轻松group by Cat1sum Q

> df %>% group_by(Cat1) %>% summarise(Sum1 = sum(Q))
# A tibble: 3 x 2
  Cat1   Sum1
  <fct> <dbl>
1 A         2
2 B         2
3 C         2

现在,我的问题是,下一步,您是否可以使用group by中的组(即ABC)在原始表中操作?例如,当sum等于每个组时,您怎么Q Cat2

意思是,对于ACat2中没有匹配项,因此Q的总和为0。对于B,第一行中只有一个匹配项,因此Q的总和为1。对于C,在第二行,第四行和第五行中都有一个匹配项,因此Q的总和为3

# A tibble: 3 x 3
  Cat1   Sum1   Sum2
  <fct> <dbl>  <dbl>
1 A         2      0
2 B         2      1
3 C         2      3

请注意,这不是我要的不是

> df %>% group_by(Cat1) %>% summarise(Sum1 = sum(Q), Sum2 = sum(Q[Cat1==Cat2]))
# A tibble: 3 x 3
  Cat1   Sum1  Sum2
  <fct> <dbl> <dbl>
1 A         2     0
2 B         2     0
3 C         2     1

@ antoine-sac在注释中建议复制df,并在Cat1(Grouped) = Cat2上进行左连接。当然,这可以解决问题,但这不是我要回答的问题。

代码:

Cat1 <- c("A","A","B","B","C","C")
Cat2 <- c("B","C","D","C","C","D")
Cat1 <- factor(Cat1, levels = c("A","B","C","D"))
Cat2 <- factor(Cat2, levels = c("A","B","C","D"))
Q <- c(1,1,1,1,1,1)
df <- data.frame(Cat1, Cat2, Q)

3 个答案:

答案 0 :(得分:1)

您可以尝试

df %>% 
  group_by(Cat1) %>% 
  summarise(sum1 = sum(Q),
            sum2 = sum(ifelse(.$Cat2 == Cat1[1], Q, 0)))
# A tibble: 3 x 3
  Cat1   sum1  sum2
  <fct> <dbl> <dbl>
1 A         2     0
2 B         2     1
3 C         2     3

使用.$,您将比较并汇总未分组的原始数据。

答案 1 :(得分:1)

我认为join是最干净的方法。考虑一下自己在6个月内再次阅读代码:您希望代码的含义显而易见。

library("dplyr")

df <- read.table(text = "  Cat1 Cat2 Q
1    A    B 1
2    A    C 1
3    B    D 1
4    B    C 1
5    C    C 1
6    C    D 1", stringsAsFactor = FALSE)

df1 <- df %>%
  group_by(Cat1) %>%
  summarise(Sum1 = sum(Q))

df2 <- df %>%
  group_by(Cat2) %>%
  summarise(Sum2 = sum(Q))

full_join(df1, df2, by = c("Cat1" = "Cat2")) %>%
  tidyr::replace_na(list(Sum1 = 0, Sum2 = 0))

# # A tibble: 4 x 3
#   Cat1   Sum1  Sum2
#   <chr> <dbl> <dbl>
# 1 A         2     0
# 2 B         2     1
# 3 C         2     3
# 4 D         0     2

使用full_join,您可以将所有值保留在Cat1Cat2中(A,B,C和D),但可以使用left_join(保留A ,B,C),right_join(保留B,C,D)或inner_join(保留B,C)。

这些分别是Cat1Cat2中的值,或者是Cat1 Cat2中的值。

这似乎很痛苦,特别是如果您有很多类别,但是如果必须执行多次以上,则实际上很容易在函数中实现自动化。

编辑:实际上,由于非标准评估,如果要使用dplyr根本不容易。这是您的操作方式:

sum_cats <- function(df, cat1, cat2, value) {
  cat1 <- enquo(cat1)
  cat2 <- enquo(cat2)
  value <- enquo(value)

  sum1 <- paste0("Sum_", quo_name(cat1))
  df1 <- df %>%
    rename(cat = !! cat1) %>%
    group_by(cat) %>%
    summarise(!! sum1 := sum(!! value))

  sum2 <- paste0("Sum_", quo_name(cat2))
  df2 <- df %>%
    rename(cat = !! cat2) %>%
    group_by(cat) %>%
    summarise(!! sum2 := sum(!! value))

  full_join(df1, df2, by = "cat") %>%
    tidyr::replace_na(rlang::list2(!! sum1 := 0, !! sum2 := 0))
}

现在,您只需致电sum_cats即可完成所有工作:

df %>%
  sum_cats(Cat1, Cat2, Q)
#   cat   Sum_Cat1 Sum_Cat2
#   <chr>    <dbl>    <dbl>
# 1 A            2        0
# 2 B            2        1
# 3 C            2        3
# 4 D            0        2

答案 2 :(得分:0)

您可能可以构造一个新列并从该新列中进行总结:

df %>% mutate(new_Quantity=ifelse(Start == End, Quantity,0)) %>% group_by(Start) %>% summarise(Sum = sum(new_Quantity))