使用tidyr::pivot_wider生成布尔宽表及values_fn参数报错问题
解决pivot_wider生成布尔值宽表的问题
首先,针对你想要将运动列转为TRUE/FALSE的需求,有几种直接实现的方法,不需要后续反转结果:
方法一:通过values_fn自定义函数生成布尔值
你之前的报错是因为!is.na不能直接作为函数传入,!是运算符,需要包装成完整的函数。我们可以调整代码如下:
library(tidyr) example_data <- data.frame( name = c("bob", "bob", "dick", "dick", "harry", "harry"), sport = c("baseball", "football", "hockey", "basketball", "football", "basketball") ) pivot_wider( example_data, names_from = sport, values_from = sport, values_fn = list(sport = function(x) TRUE), # 存在的运动标记为TRUE values_fill = list(sport = FALSE) # 缺失的运动标记为FALSE )
运行后直接得到目标结果:
name baseball football hockey basketball
1 bob TRUE TRUE FALSE FALSE
2 dick FALSE FALSE TRUE TRUE
3 harry FALSE TRUE FALSE TRUE
方法二:先构造布尔列再透视
另一种更直观的方式是先给数据添加一个值为TRUE的辅助列,再进行透视,逻辑更清晰:
example_data$has_sport <- TRUE pivot_wider( example_data, names_from = sport, values_from = has_sport, values_fill = list(has_sport = FALSE) )
这个方法同样能得到预期结果,代码可读性更高。
关于values_fn参数的报错原因和使用说明
你之前的代码values_fn = list(sport = !is.na)报错,核心原因是:
!is.na不是合法的函数对象——!是一元运算符,不能直接和is.na组合成函数传递。如果要使用is.na的逻辑反转,需要包装成匿名函数(比如function(x) !is.na(x)),但在这个场景下其实不需要,因为我们只需要标记“存在该运动”为TRUE,直接返回TRUE更简单。values_fn的作用是对每个分组(这里是name+sport的组合)的values_from列的值进行聚合计算。当你的数据中每个name和sport的组合唯一时,每个分组只有一个值,此时values_fn就是对这个单一值做转换。
values_fn基础使用场景示例
- 统计同一
name下某运动的重复次数:values_fn = list(sport = length) - 将同一
name的运动合并为字符串:values_fn = list(sport = paste, collapse = ", ") - 对数值列求分组均值:
values_fn = list(score = mean)
简单来说,values_fn需要接收一个函数(内置函数或自定义匿名函数均可),这个函数会被应用到每个分组的values_from列子集上,返回单一值作为宽表单元格内容。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

