如何在data.table的by参数中向函数传递字符向量?
解决data.table中by参数传递字符向量给函数的问题,以及按月份聚合日期的需求
我来帮你搞定这两个问题,先从核心的by参数传递字符向量的问题说起,再讲日期聚合的规范做法。
为什么你的代码无效?
你之前试的这两行代码:
df[, .(n = .N), by = str_sub(chosen_col, 1, 7)] df[, .(n = .N), by = eval(str_sub(chosen_col, 1, 7))]
问题出在:str_sub(chosen_col, 1,7)是对字符串"dates"本身截取(结果是"dates"前7个字符,也就是"dates"),而不是对df$dates列里的日期值操作。eval在这里也没起到作用,因为它没有引用到data.table内部的列数据。
正确的解决方法(核心问题:传递字符向量给by参数的函数)
方法1:用get()获取列并处理
get()函数可以从data.table的环境中取出指定名称的列,然后直接对列值应用函数:
library(data.table) library(stringr) df <- data.table(dates = c('2017-01-01', '2017-01-05')) chosen_col <- 'dates' # 正确写法:用get()拿到列的值,再用str_sub处理 df[, .(n = .N), by = str_sub(get(chosen_col), 1, 7)]
运行后会得到按2017-01分组的计数结果。
方法2:用.SDcols和.SD操作列
.SDcols指定要操作的列,.SD代表这些列组成的子数据集,用.SD[[1]]取出对应列的值:
df[, .(n = .N), by = .(month = str_sub(.SD[[1]], 1, 7)), .SDcols = chosen_col]
这种方式适合同时处理多列的场景,这里单列也适用,还能给分组键起个清晰的名字month。
按月份聚合日期的规范做法
既然你提到了日期聚合的变通方法,这里再补充几个更规范的日期处理方式(推荐先把字符串转成Date类型):
# 先把dates列转成Date类型 df[, dates := as.Date(dates)] # 方法1:用lubridate的yearmonth函数直接生成年月分组 library(lubridate) df[, .(n = .N), by = yearmonth(dates)] # 方法2:拆分成年和月分组,或者合并成年月字符串 df[, .(n = .N), by = .(year = year(dates), month = month(dates))] # 合并成年月格式字符串 df[, .(n = .N), by = sprintf("%04d-%02d", year(dates), month(dates))]
这些方法比直接截取字符串更可靠,能避免日期格式不规范带来的问题。
内容的提问来源于stack exchange,提问作者MLEN
相关产品推荐
相关产品推荐

