dplyr中的group_by日期列

时间:2017-05-19 18:36:39

标签: r dplyr

经过广泛搜索这个问题,我仍然找不到解决方案。我有一个简单的数据框,有43行和2列。我的第一列包含两个日期。第一个日期打印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

我不明白为什么Date没有被分组。我已经尝试将Date更改为一个因子,因为它在这里,字符,日期对象,甚至POSIXct,但我的结果始终是总数据帧max和min。

非常感谢任何帮助。

感谢。

5 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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

答案 2 :(得分: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)) 

答案 3 :(得分:1)

summarisedplyr软件包中都有plyr个函数。我猜想软件包的加载顺序意味着函数的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已将其发布为对原始问题的评论。

答案 4 :(得分: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"))