总结?计算基于另一列的列中的出现次数

时间:2019-03-01 16:21:37

标签: r dplyr summarize

我相信这可能是一个简单的解决方案,但是我在描述我需要做什么(以及要搜索的内容)时遇到了麻烦。我认为我需要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

3 个答案:

答案 0 :(得分:5)

尽管年龄较大,并且可能在弃用的路径上,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

答案 1 :(得分:4)

我不确定为什么我会使用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

答案 2 :(得分:4)

一种选择是将table内的summarise用作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