R语言apply族函数如何按行传递多列参数给自定义函数
apply族逐行传参实现mtcars自定义打标
你写的hotornot是接收标量入参的判断函数,核心需求是逐行提取hp/cyl/name三列的值传入函数,把返回的属性标签回写到name列,下面是不同apply族函数的可运行实现,附日常使用中最容易踩的误区。
适配场景的实现方案
1. 多向量逐元素匹配:mapply()(最适合当前需求)
mapply本身就是为多向量逐元素匹配设计的,会对多个输入向量按相同索引位置逐次取元素传入函数,完全匹配你需要传3个列逐行计算的场景,不会出现类型强转的问题。
# 先初始化带原始车辆名称的name列 mtcars$name <- rownames(mtcars) # 逐行传参计算新标签 mtcars$name <- mapply( FUN = hotornot, # 带参数名传值,避免顺序错位 horsepower = mtcars$hp, cylinders = mtcars$cyl, name = mtcars$name )
这个方法的好处是直接保留原列的数据类型,不像逐行遍历的apply那样,会把所有列统一转成字符型,导致数值判断出错。
2. 按行维度遍历:apply()
用apply逐行遍历的时候一定要注意:数据框传入apply后会先被转成矩阵,矩阵要求所有元素为统一类型,原来的数值列会被强转成字符型,必须在函数内部把对应列转回数值类型,才能正常做大小判断。
mtcars$name <- apply( X = mtcars, MARGIN = 1, # *MARGIN=1*是逐行遍历,*MARGIN=2*是逐列遍历 FUN = function(row_vec) { hotornot( horsepower = as.numeric(row_vec["hp"]), cylinders = as.numeric(row_vec["cyl"]), name = row_vec["name"] ) } )
日常编写时的常见错误
- 用apply传参时图省事直接通过
...传全局的列值,比如写apply(mtcars, 1, hotornot, horsepower = hp, cylinders = cyl, name = name),这里传进去的hp/cyl是全局环境里长度为32的整列向量,不是逐行的单值,会直接触发“条件长度大于1”的警告,最后只取第一个值的判断结果,完全不符合预期。 - 用apply的时候忘了类型强转,直接把行向量里的hp、cyl传给函数,字符型的数值会导致比较逻辑出现精度或类型匹配问题。
- 用mapply的时候省略参数名,按位置传参导致入参错位,比如把车辆名称文本传给cyl参数、把气缸数数值传给name参数,判断结果完全偏离自己写的规则。
结果快速核对
写完代码可以快速验证规则有没有生效:
# 统计两类标签的车辆数量 table(mtcars$name) # 查看所有被标记为scrap truck的车辆,确认符合“马力<200、气缸数<5、不是Merc 240D”的规则 mtcars[mtcars$name == "scrap truck", c("hp", "cyl", "name")] # 确认Merc 240D因为规则排除,不会被标记为scrap truck mtcars["Merc 240D", "name"]
内容的提问来源于stack exchange,提问作者Smon
相关产品推荐
相关产品推荐

