【问题标题】:group_by date column in dplyrdplyr 中的 group_by 日期列
【发布时间】:2017-05-19 18:36:38
【问题描述】:

在对这个问题进行了大量搜索之后,我仍然找不到解决方案。我有一个包含 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,但我的结果始终是总数据帧的最大值和最小值。

非常感谢任何帮助。

谢谢。

【问题讨论】:

  • 使用group_by,而不是用于标准评估的group_by_
  • 这是我的错误,因为我尝试了 group_by。 group_by 和 group_by_ 都产生相同的结果:/
  • 我测试了您的代码并将group_by_ 替换为group_by。它奏效了。
  • 我也使用下面的代码来产生下面的结果。
  • 你知道我的想法---我刚刚遇到了同样的问题---可能不小心被加载了plyr。然后它崩溃到对整个数据框进行汇总。我倾向于每次都使用dplyr::summarise,但瞬间忘记了这一点。我通常不会加载 plyr 但肯定是另一个包调用了它。

标签: r dplyr


【解决方案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 会话并再次打开。不知道为什么这不起作用。
【解决方案2】:
NWS_temps1 %>%
group_by(as.character(Date)) %>% 
summarise(Tmax = max(Temperature_F), Tmin= min(Temperature_F))

【讨论】:

  • as.character 不是必需的
【解决方案3】:

其他人使用dplyr 提供的答案应该有效。但是,如果由于某些原因 dplyr 不起作用。这是使用来自 base 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)) 

【讨论】:

  • 谢谢你,我会保留这个作为未来的参考!
【解决方案4】:

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 已经将此作为对原始问题的评论发布。

【讨论】:

    【解决方案5】:

    在将表示为数字的日期/时间字段转换为带有 as.Date() 的日期时,我能够复制原始的 group_by() 问题 - 使用从 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")) 
    

    【讨论】:

      猜你喜欢
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      • 2018-07-06
      • 1970-01-01
      • 2015-09-02
      • 1970-01-01
      • 2018-09-26
      相关资源
      最近更新 更多