使用[[]]和向量索引数据框时,日期列被强制转换为数值类型。

11

我创建了一个带有Date类型列的数据框。当使用[[和数字向量对数据框进行索引时,日期将变成数字。这在使用purrr::pmap时会导致问题。有人能解释一下为什么会发生这种情况吗?是否有解决方法?

示例:

x <- data.frame(d1 = lubridate::ymd(c("2018-01-01","2018-02-01")))

class(x$d1)
# [1] "Date"

x[[1]]
# [1] "2018-01-01" "2018-02-01"

x[[c(1, 1)]]
# [1] 17532

1
原来这是一个持续存在的问题:https://github.com/tidyverse/purrr/issues/358 - MrHopko
1
是的,你注意到@hadley在那里的评论了吗 - Henrik
1
只是出于好奇,为什么要使用 x[[c(1, 1)]] 而不是 x[1, 1] - Cristian E. Nuno
1
x[[c(1,1)]]purrr::pmap 迭代数据框时访问值的方式。这就是我遇到上述问题的地方。 - MrHopko
5
help(Extract)中 - 子集(除非使用空索引)会删除除名称、维度和维度名称之外的所有属性。 请注意,子集索引不同。在x[[1]]中,您正在进行索引,在x[[c(1, 1)]]中,您正在进行子集操作,因此会丢失属性。 - Rich Scriven
显示剩余4条评论
1个回答

5

概述

阅读完为什么在R中使用unlist()会清除日期unlist()的文档后,您需要手动使用base::c()函数来防止purrr::map()将Date对象强制转换为整数。

加载mikmart的purrr::pmap() PR版本

阅读了pmap strips Date后,看起来有个非常棒的人提交了一个拉取请求,以解决在purrr::pmap()底层索引重构版本中发生的这个问题。

使用devtools::dev_mode(),您可以安装mikmart/purrr的“pmap”分支版本的purrr,同时保留Date对象并使用pmap()

# ******pmap() example ****
# load necessary packages -----
library(devtools)
library(lubridate)

# enter dev mode so you don't have to uninstall the cran version of purrr ----
dev_mode(on = TRUE)

# install mikmart's PR to fix the coercing of Dates to integer ----
install_github(repo = "mikmart/purrr", ref = "pmap")

# load mikmart's PR version of purrr ----
library(purrr)

# load necessary data
x <- data.frame(d1 = lubridate::ymd(c("2018-01-01","2018-02-01")))

# for the first column in x ----
# give me each element
# note: no need for c()
list.of.dates <-
  x %>%
  pmap(.f = ~ .x)

# view results -----
list.of.dates
# [[1]]
# [1] "2018-01-01"
# 
# [[2]]
# [1] "2018-02-01"

# view the class of each list -----
map_chr(list.of.dates, class) # [1] "Date" "Date"
#
# 
# turn off dev mode ---
dev_mode(on = FALSE)
#
# restart R -----
# Manually hit Shift+Cmd+F10 or point in click under the "Session" tab
#
# clear global environment ----
rm(list = ls())
#
# ******map() example********
# load necessary packages -----
library(tidyverse)
library(lubridate)

# load necessary data ----
x <- data.frame(d1 = lubridate::ymd(c("2018-01-01","2018-02-01")))

# from the first column ------
# give me each element
# and ensure the dates don't get coerced to integers
list.of.dates <-
  x$d1 %>%
  map(.f = ~ .x %>% c()) 

# view results -----
list.of.dates
# [[1]]
# [1] "2018-01-01"
# 
# [[2]]
# [1] "2018-02-01"

# # view the class of each list -----
map_chr(list.of.dates, class) # [1] "Date" "Date"

# end of script #

非常有趣的处理包更新过程(因为它在 purrr 上没有更新),我已经记录下来了。在 install_github(repo = "mikmart/purrr", ref = "pmap") 调用中的 ref = 'pmap' 表示只安装了重构后的 pmap 函数;我的理解正确吗? - Chris
@Chris没错。看起来索引重构是在src/map.c脚本中进行的。 - Cristian E. Nuno
1
太好了,Cristian。我认为你上面的描述和代码将通过编辑为“# load mikmart的PR版本的purrr pmap ----”使其完全明确,所有的歧义都消失了。 - Chris

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