【问题标题】:Summarise? Count occurences in column based on another column总结?根据另一列计算列中的出现次数
【发布时间】:2019-07-23 17:14:03
【问题描述】:

我相信这可能有一个简单的解决方案,但我无法描述我需要做什么(以及要搜索什么)。我想我需要summarize 函数。我的目标输出在最底部。

我正在尝试计算另一列中每个唯一值之间某个值的出现次数。这是一个示例df,希望能说明我需要做什么。

library(dplyr)

set.seed(1)
df <- tibble("name" = c(rep("dinah",2),rep("lucy",4),rep("sora",9)),
             "meal" = c(rep(c("chicken","beef","fish"),5)),
             "date" = seq(as.Date("1999/1/1"),as.Date("2000/1/1"),25),
             "num.wins" = sample(0:30)[1:15])

除其他外,我正在尝试使用这些数据总结(总结)每个名字所吃的饭菜类型。

df
# A tibble: 15 x 4
   name  meal    date       num.wins
   <chr> <chr>   <date>        <int>
 1 dinah chicken 1999-01-01        8
 2 dinah beef    1999-01-26       11
 3 lucy  fish    1999-02-20       16
 4 lucy  chicken 1999-03-17       25
 5 lucy  beef    1999-04-11        5
 6 lucy  fish    1999-05-06       23
 7 sora  chicken 1999-05-31       27
 8 sora  beef    1999-06-25       15
 9 sora  fish    1999-07-20       14
10 sora  chicken 1999-08-14        1
11 sora  beef    1999-09-08        4
12 sora  fish    1999-10-03        3
13 sora  chicken 1999-10-28       13
14 sora  beef    1999-11-22        6
15 sora  fish    1999-12-17       18

我在以下我感兴趣的其他计算方面取得了进展:

df %>% 
  group_by(name) %>% 
  summarise(count=n(),
            medianDate=median(date),
            life=(max(date)-min(date)),
            wins=sum(num.wins))

# A tibble: 3 x 5
  name  count medianDate life      wins
  <chr> <int> <date>     <time>   <int>
1 dinah     2 1999-01-13  25 days    19
2 lucy      4 1999-03-29  75 days    69
3 sora      9 1999-09-08 200 days   101

我的目标是为每种食物添加一个额外的列,并在每一行中显示该食物出现的总和,如下所示:

  name  count medianDate life      wins  chicken  beef  fish
1 dinah     2 1999-01-13  25 days    19        1     1     0
2 lucy      4 1999-03-29  75 days    69        1     1     2
3 sora      9 1999-09-08 200 days   101        3     3     3

【问题讨论】:

  • 我猜你可以使用 tidyr 包中的spread 并与你的汇总表合并/加入。

标签: r dplyr summarize


【解决方案1】:

reshape2::dcast 虽然较旧,并且可能处于弃用路径,但在这方面做得很好:

reshape2::dcast(df, name ~ meal)
#    name beef chicken fish
# 1 dinah    1       1    0
# 2  lucy    1       1    2
# 3  sora    3       3    3

您可以将公式理解为rows ~ columns。默认情况下,它将使用length 函数聚合列中的值——它给出了你想要的,每个的计数。

这可以很容易地加入到您的摘要数据中:

df %>% 
  group_by(name) %>% 
  summarise(count=n(),
            medianDate=median(date),
            life=(max(date)-min(date)),
            wins=sum(num.wins)) %>%
  left_join(reshape2::dcast(df, name ~ meal))
# # A tibble: 3 x 8
#   name  count medianDate life      wins  beef chicken  fish
#   <chr> <int> <date>     <time>   <int> <int>   <int> <int>
# 1 dinah     2 1999-01-13  25 days    19     1       1     0
# 2 lucy      4 1999-03-29  75 days    69     1       1     2
# 3 sora      9 1999-09-08 200 days   101     3       3     3

【讨论】:

    【解决方案2】:

    一种选择是在summarise 中使用table 作为list 列,unnest 然后将spread 使用为“宽”格式

    library(tidyverse)
    df %>% 
      group_by(name) %>%
      summarise(count=n(),
                 medianDate=median(date),
                 life=(max(date)-min(date)),
                 wins=sum(num.wins),
                 n = list(enframe(table(meal))) ) %>%
      unnest %>%
      spread(name1, value, fill = 0)
    # A tibble: 3 x 8
    #  name  count medianDate life      wins  beef chicken  fish
    #  <chr> <int> <date>     <time>   <int> <dbl>   <dbl> <dbl>
    #1 dinah     2 1999-01-13  25 days    19     1       1     0
    #2 lucy      4 1999-03-29  75 days    69     1       1     2
    #3 sora      9 1999-09-08 200 days   101     3       3     3
    

    【讨论】:

    • 这也很棒,如果我没有使用选中的答案,我会使用这个。谢谢
    【解决方案3】:

    我不完全确定为什么我会得到 life 的时髦格式,但我认为这可以满足您计算餐食类型的需要。

    df %>% 
      group_by(name) %>% 
      summarise(count=n(),
                medianDate=median(date),
                life=(max(date)-min(date)),
                wins=sum(num.wins),
                chicken = sum(meal == "chicken"),
                beef = sum(meal == "beef"),
                fish = sum(meal == "fish"))
    
    # A tibble: 3 x 8
      name  count medianDate life        wins chicken  beef  fish
      <chr> <int> <date>     <time>     <int>   <int> <int> <int>
    1 dinah     2 1999-01-13 " 25 days"    19       1     1     0
    2 lucy      4 1999-03-29 " 75 days"    69       1     1     2
    3 sora      9 1999-09-08 200 days     101       3     3     3
    

    【讨论】:

    • 感谢这个答案很有用,而且比我想象的要简单得多。我检查了 gregors 的答案,因为在我的情况下,我有很多“食物”,他的方法不需要我手动列出它们。再次感谢
    猜你喜欢
    • 2021-04-12
    • 1970-01-01
    • 2021-09-09
    • 2022-01-04
    • 2019-03-27
    • 2022-06-16
    • 2019-09-03
    • 2017-08-20
    • 1970-01-01
    相关资源
    最近更新 更多