【问题标题】:Using dplyr to apply a function of several columns of an R data frame使用 dplyr 应用 R 数据框的几列的函数
【发布时间】:2016-05-09 15:24:02
【问题描述】:

使用 dplyr 的“动词”,如果该函数依赖于数据帧的多个列,我如何将(通用)函数应用于 R 数据帧的列?

这是我所面临的情况类型的具体示例。我有一个这样的数据框:

df <- data.frame(
    d1 = c('2016-01-30 08:40:00 UTC', '2016-03-06 09:30:00 UTC'),
    d2 = c('2016-01-30 16:20:00 UTC', '2016-03-06 13:20:00 UTC'),
    tz = c('America/Los_Angeles', 'America/Chicago'), stringsAsFactors = FALSE)

我想将 UTC 时间转换为当地时间,以获得这样的数据框:

                   d1                  d2                  tz
1 2016-01-30 00:40:00 2016-01-30 08:20:00 America/Los_Angeles
2 2016-03-06 03:30:00 2016-03-06 07:20:00     America/Chicago

为此,我想将以下函数(使用 lubridate 库将 UTC 时间转换为本地时间)应用于日期列:

getLocTime <- function(d, tz) {
    as.character(with_tz(ymd_hms(d), tz))
}

使用dplyr,好像是变换

df %>% mutate(d1 = getLocTime(d1, tz), d2 = getLocTime(d2, tz))

应该可以解决问题。但是,它因投诉Error in eval(expr, envir, enclos): invalid 'tz' value 而失败。

我设法转换为当地时间的唯一方法是使用相当笨拙的分配

df[c('d1', 'd2')] <- lapply(c('d1', 'd2'),
                            function(x) unlist(Map(getLocTime, df[[x]], df$tz)))

实际上有没有一种自然的方法可以使用 dplyr 习惯用法来执行这种转换?

【问题讨论】:

  • 这调用getLocTime(c("2016-01-30 08:40:00 UTC", "2016-03-06 09:30:00 UTC"), c("America/Los_Angeles", "America/Chicago")) 为第一个mutate,这不起作用。您可以矢量化您的功能,例如vgetLocTime &lt;- Vectorize(getLocTime, c("d", "tz")).
  • Vectorize 你的函数,正如@lukeA 建议的那样,那么你也可以使用mutate_each 来更容易地改变多列:df %&gt;% mutate_each(funs(getLocTime(., tz)), matches("d"))
  • @lukeA:完美,行得通!谢谢你。 (dplyr 文档可能更明确地说明在应用列变异函数时需要矢量化......)
  • matches 记录在select 下,这是用于选择数据框列的动词。 matches 允许您使用正则表达式选择列。在这种情况下,“d”将匹配名称中包含“d”的任何列。根据需要调整您的真实列名,或者您可能更喜欢使用select 下记录的其他帮助函数之一来选择数据框的列。
  • 是的,只有有效的正则表达式才能与 matches 一起使用。您可以使用matches("d[12]")(相当于,但比matches("d1|d2") 短),但除非您需要排除包含“d”和其他字符的其他列,否则单独使用"d" 即可。例如,如果您只想要以“d”开头并以 1 到 5 结尾的列,您可以使用matches("^d.*[1-5]$")

标签: r dataframe map-function


【解决方案1】:

正如lukeA 所提到的,问题的出现是因为getLocTime 没有矢量化。因此,要么按照建议对函数进行矢量化,要么按行执行函数:

 df %>% rowwise() %>% mutate(d1 = getLocTime(d1, tz), d2 = getLocTime(d2, tz))

这确保getLocTime 是用单个数字而不是向量调用的。我让你来决定哪种方法更快。

【讨论】:

  • 我没有检查过时间,但是根据过去的经验,rowwise 往往很慢。
猜你喜欢
  • 2016-10-20
  • 2020-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多