为何filter在lapply中表现异常?按时间戳分割数据帧失败求助
解决按时间戳分割数据帧得到空结果的问题
这个问题我之前也碰到过,核心原因是dplyr的非标准求值(NSE)特性和你匿名函数的参数命名冲突了,我来帮你拆解清楚:
问题根源
你的数据框里正好有一列名为x,而你在lapply的匿名函数里把参数也命名为x。当你调用filter(z, ts == x)时,dplyr会优先在数据框z的列中查找x——也就是那个值全为"a"的列,拿它和数值型的ts列比较,结果自然全是FALSE,所以返回了空数据框。
解决方案
这里有几种靠谱的修复方式:
1. 重命名函数参数(最直观)
把匿名函数的参数名改成和数据框列不冲突的名字,比如tstamp:
library(dplyr) df <- data.frame( x=rep("a", 3), ts=c(1518904061180, 1518904061180, 1518904087257)) out <- lapply( unique(df$ts), function(tstamp, z){ filter(z, ts == tstamp) }, z=df)
这样dplyr就不会把参数和数据框列混淆,能正确匹配时间戳。
2. 使用dplyr的标准求值语法
用!!(非标准求值的"强制解析"运算符)告诉dplyr,这里的x是外部函数参数,不是数据框的列:
library(dplyr) df <- data.frame( x=rep("a", 3), ts=c(1518904061180, 1518904061180, 1518904087257)) out <- lapply( unique(df$ts), function(x, z){ filter(z, ts == !!x) }, z=df)
3. 改用base R的subset函数
如果你不想纠结dplyr的作用域问题,base R的subset函数在这种场景下的作用域处理更直观:
df <- data.frame( x=rep("a", 3), ts=c(1518904061180, 1518904061180, 1518904087257)) out <- lapply( unique(df$ts), function(x, z){ subset(z, ts == x) }, z=df)
验证结果
运行上述任意一种修改后的代码,你都会得到预期的结果:
out[[1]]包含前两行时间戳为1518904061180的数据out[[2]]包含第三行时间戳为1518904087257的数据
内容的提问来源于stack exchange,提问作者Matt Munson
相关产品推荐
相关产品推荐

