在dplyr中按日期列分组

3

在对此问题进行了广泛搜索之后,我仍然找不到解决方案。我的数据框很简单,只有两列,共43行。第一列包含两个日期,其中一个日期出现了19次,另一个日期出现了24次。第二列是温度。我想按日期查找最高和最低温度,但我的代码一直打印整个数据集的最高和最低温度。

数据:

Date <- c(rep(x = "2017-05-18", each= 19), rep(x = "2017-05-19", each= 24))


Temperature_F <- c(35, 35, 42, 49, 57, 63, 64, 67, 70, 71, 72, 71, 72, 70, 66, 61, 57, 54, 50, 49, 45, 44, 44, 42, 40, 39, 47, 53, 61, 67, 69, 
    72, 75, 76, 77, 76, 77, 75, 71, 66, 62, 58, 54)

NWS_temps1 <- data.frame(Date, Temperature_F)

这是我的 dplyr 代码,但我一直得到整个温度列的最大值和最小值,而我认为它应该给我每天的最高温度和最低温度。

NWS_temps1 <- tbl_df(NWS_temps1)

 NWS_temps1 %>%
  group_by(Date) %>% 
  summarise(Tmax = max(Temperature_F), Tmin= min(Temperature_F))

我得到的输出是:
 Tmax Tmin
  77   35

当我希望:

Date        Tmax Tmin
2017-05-18   72   35
2017-05-19   77   39

我不明白为什么日期没有按照应有的方式分组。我已经尝试过将日期更改为因子,如此处所示,字符、日期对象甚至POSIXct,但结果总是整个数据框的最大值和最小值。
非常感谢任何帮助。
谢谢。

1
使用 group_by,而不是用于标准评估的 group_by_ - www
那是我的错误,因为我尝试了group_by。无论是group_by还是group_by_都会产生相同的结果 :/ - user3720887
1
我测试了你的代码,并将 group_by_ 替换为 group_by。它可以正常工作。 - www
1
我也使用了以下代码来产生下面的结果。 - Julia Silge
我的 R 会话肯定有问题,因为在关闭后重新打开会话后,我得到了正确的结果。真的很奇怪。非常感谢您的帮助。 - user3720887
1
你知道我在想什么吗——我刚遇到了同样的问题——可能是意外加载了 plyr。然后它会折叠成对整个数据框进行汇总。我倾向于每次使用 dplyr::summarise,但这一次忘记了。我通常不会加载 plyr,但可能是其他包调用了它。 - Kim
5个回答

1
NWS_temps1 %>%
group_by(as.character(Date)) %>% 
summarise(Tmax = max(Temperature_F), Tmin= min(Temperature_F))

1
as.character 不是必需的。 - www

1

看起来您正在使用标准评估版本的group_by_(),而不是NSE版本的group_by()。请尝试去掉下划线:

NWS_temps1 %>%
    group_by(Date) %>% 
    summarise(Tmax = max(Temperature_F), Tmin= min(Temperature_F))

#> # A tibble: 2 x 3
#>         Date  Tmax  Tmin
#>        <chr> <dbl> <dbl>
#> 1 2017-05-18    72    35
#> 2 2017-05-19    77    39

有趣啊。我尝试了两种方法,但结果都一样。你的方法能行,让我很惊讶。我要试着关闭 R 会话然后重新打开。不知道为什么这个没法运行。 - user3720887

1

dplyrplyr 包中都有 summarise 函数。我猜测包的加载顺序导致加载了 plyr 版本的函数,这就是你看到的结果。你可以手动指定要使用的函数版本,方法是在函数名前加上包名,像这样:dplyr::summarise(...)

# Specify the plyr version:
> NWS_temps1 %>%
+   group_by(Date) %>% 
+   plyr::summarise(Tmax = max(Temperature_F), Tmin= min(Temperature_F))
  Tmax Tmin
1   77   35

# Specify the dplyr version:
> NWS_temps1 %>%
+   group_by(Date) %>% 
+   dplyr::summarise(Tmax = max(Temperature_F), Tmin= min(Temperature_F))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 2 x 3
  Date        Tmax  Tmin
  <fct>      <dbl> <dbl>
1 2017-05-18    72    35
2 2017-05-19    77    39

编辑:我刚刚注意到Kim已经在原问题的评论中发布了这个。


1
其他人使用 dplyr 提供的答案应该有效。但是,如果由于某些原因 dplyr 无法使用,这里提供了一种使用基本 R 中的 tapply 的解决方案。
dt <- data.frame(Date = unique(NWS_temps1$Date),
                 Tmax = tapply(NWS_temps1$Temperature_F, NWS_temps1$Date, FUN = max),
                 Tmin = tapply(NWS_temps1$Temperature_F, NWS_temps1$Date, FUN = min)) 

谢谢,我会将这个作为以后的参考! - user3720887

0

我能够复制原始的group_by()问题,当将表示为数字的日期/时间字段转换为as.Date()日期时 - 这可能发生在使用从Excel文件导入的日期/时间字段时,因为Excel将日期存储为数字。

library(dplyr)

dt = c(43167.86, 43167.59, 43167.59, 43167.23, 43182.60, 43168.17, 43182) 
df <- data_frame(date = dt)

df %>% 
  mutate(date = as.Date(date, origin = '1899-12-30')) %>% 
  group_by(date) %>% 
  summarize(obs = n())
# A tibble: 6 x 2
  date         obs
  <date>     <int>
1 2018-03-08     1
2 2018-03-08     2
3 2018-03-08     1
4 2018-03-09     1
5 2018-03-23     1
6 2018-03-23     1

这个问题导致了“2018-03-08”和“2018-03-23”的多个版本。其中一行“2018-03-08”有两个观察值,因为有两个“43167.59” - 相同的日期和时间,而另外两个43167则具有不同的时间。这似乎可能是一个与dplyr相关的问题,因为table(as.Date(df$date, origin = '1899-12-30'))按预期工作。

一个选择是使用lubridate::ymd()

library(lubridate)

df %>% 
  mutate(date = as.Date(date, origin = '1899-12-30')) %>% 
  mutate(date = ymd(date)) %>% 
  group_by(date) %>% 
  summarize(obs = n())
# A tibble: 3 x 2
  date         obs
  <date>     <int>
1 2018-03-08     4
2 2018-03-09     1
3 2018-03-23     2

另一个(粗糙的)解决方案是将日期转换为字符,然后再转回日期(如果您想将其保留为日期)。
df %>% 
  mutate(date = as.Date(date, origin = '1899-12-30')) %>% 
  mutate(date = as.Date(as.character(date))) %>% 
  group_by(date) %>% 
  summarize(obs = n())

最好的解决方案可能是退一步,在使用readxl::read_excel()导入时将列类型设置为日期。这将把字段作为日期/时间导入,然后as.Date()group_by()将按预期工作。来自vignette的示例:

library(readxl)

df <- read_excel(readxl_example("type-me.xlsx"), sheet = "date_coercion",
                 col_types = c("date", "text")) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接