如何正确使用dplyr管道运算符、修复apply报错及访问父级dataframe数据
问题修复方案
1. 管道写法报错修复
报错原因:dplyr管道%>%默认会将左侧运算结果作为右侧函数的第一个输入参数,你原来的写法中,管道会把原始dataframe直接传给apply的第一个参数,而你又手动写了as.matrix(.)作为apply的第二个参数,导致apply的参数顺序完全错乱:原本第二个参数MARGIN被传入了矩阵,第三个参数被传入了数值1,R会把第三个参数当成要执行的函数,才会报'1' is not a function的错误。
修复方法很简单,用大括号{}包裹apply的全部逻辑,阻断管道自动传参的默认行为,手动控制.的使用即可,修复后的代码如下:
library(dplyr) library(zoo) data.frame('col1' = c('C', 'A', 'B', 'A'), 'col2' = c(1,2,3,4)) %>% { apply(as.matrix(.), 1, function(ii) { merge(data.frame('xx' = sample(letters[1:10], 5, replace = T), 'val1' = 1:5), data.frame('xx' = sample(letters[1:5], 5, replace = T), 'val2' = 21:25), by = 'xx', all = T) %>% mutate('Info' = ii['col1']) %>% `colnames<-`(c('yy0', 'yy1', 'yy2', 'yy3')) }) }
2. 访问父级dataframe的信息实现
在大括号的作用域内,.就代表管道传入的原始父级dataframe,你可以直接在apply的函数内调用它的列做计算,比如要取col2的最小值,直接用min(.$col2)即可。也可以提前把需要的父级参数计算存储在大括号作用域内,避免循环中重复计算降低性能,修改后的代码如下:
library(dplyr) library(zoo) data.frame('col1' = c('C', 'A', 'B', 'A'), 'col2' = c(1,2,3,4)) %>% { # 提前计算父级df的col2最小值,仅计算1次 min_col2 <- min(.$col2) apply(as.matrix(.), 1, function(ii) { merge(data.frame('xx' = sample(letters[1:10], 5, replace = T), 'val1' = 1:5), data.frame('xx' = sample(letters[1:5], 5, replace = T), 'val2' = 21:25), by = 'xx', all = T) %>% mutate('Info' = min_col2) %>% `colnames<-`(c('yy0', 'yy1', 'yy2', 'yy3')) }) }
如果需要调用父级df的其他信息,都可以通过.$列名的方式直接取值。
内容的提问来源于stack exchange,提问作者Brian Smith
相关产品推荐
相关产品推荐

