r - 在R中的多个数据帧的函数中结合for循环和变异
问题描述
我希望我能对我的问题有所了解。基本上,我想在几个不同的数据集中创建相同的变量集(它们是基于异常值、抗议答案等的原始数据集的子集)。我已经尝试了很多东西,但我完全被难住了。
首先,我意识到使用 eval(parse( 是违反建议的,但是,我不是最有效的编码器,这符合我的目的。无论如何,我的目标基本上是创建一组变量 - X_3、X_4、X_5 等。这是一组其他变量的年份(x12) - z1_1、z2_1、z3_1 等。为此,我有以下代码,当我单独输入“数据”所在的每个数据集名称时,该代码有效。
编辑:数据预期
#what it looks like now
responseid z3_1 z4_1 z5_1
1 1 4.720 7.08 NA
2 2 1.180 NA 1.18
3 3 1.180 NA 1.18
4 4 2.596 3.54 NA
5 5 15.340 NA NA
6 6 2.360 NA 2.36
#what i'd like it look like:
responseid z3_1 z4_1 z5_1 X_3 X_4 X_5
1 1 4.720 7.08 NA 56.640 84.96 NA
2 2 1.180 NA 1.18 14.160 NA 14.16
3 3 1.180 NA 1.18 14.160 NA 14.16
4 4 2.596 3.54 NA 31.152 42.48 NA
5 5 15.340 NA NA 184.080 NA NA
6 6 2.360 NA 2.36 28.320 NA 28.32
#dput
#original
structure(list(responseid = c(1L, 2L, 3L, 4L, 5L,
6L), z3_1 = c(4.72, 1.18, 1.18, 2.596, 15.34, 2.36), z4_1 = c(7.08,
NA, NA, 3.54, NA, NA), z5_1 = c(NA, 1.18, 1.18, NA, NA, 2.36), class = "data.frame", row.names = c(NA, 6L))
#expected
structure(list(responseid = c(1L, 2L, 3L, 4L, 5L,
6L), z3_1 = c(4.72, 1.18, 1.18, 2.596, 15.34, 2.36), z4_1 = c(7.08,
NA, NA, 3.54, NA, NA), z5_1 = c(NA, 1.18, 1.18, NA, NA, 2.36),
X_3 = c(56.64, 14.16, 14.16, 31.152, 184.08, 28.32), X_4 = c(84.96,
NA, NA, 42.48, NA, NA), X_5 = c(NA, 14.16, 14.16, NA, NA,
28.32)), class = "data.frame", row.names = c(NA, 6L))
但我想对几个数据集执行此操作,因此我希望使用一个函数来运行每个 df。
for (i in 3:9){
X.varname <- paste0("X_",i)
data <- data %>%
mutate(
!!X.varname := eval(parse(text=paste0("z", i, "_1")))*12
)
}
但是,当我尝试将其放入一个函数中(以便我可以在数据帧列表上运行它)时,什么也没有发生:
f.test <- function(data){
for (i in 3:9){
X.varname <- paste0("X_",i)
data <- data %>%
mutate(
!!X.varname := eval(parse(text=paste0("z", i, "_1")))*12
)
}
}
有谁知道为什么会这样?这是我在 StackOverflow 上的第一个问题,因此如果任何格式不正确,我深表歉意。
解决方案
什么都没有发生,因为该函数没有返回任何东西。通常您不需要return
在 R 中显式指定某些内容,因为 R 会自动返回最后一个对象。但这是一个 for 循环,意味着它什么也不返回。
为了避免这个问题,只需指定你的函数应该返回什么,即。data
:
f.test <- function(data){
for (i in 3:5){
X.varname <- paste0("X_",i)
data <- data %>%
mutate(
!!X.varname := eval(parse(text=paste0("z", i, "_1")))*12
)
}
return(data)
}
顺便说一句,您是对的,eval(parse(x))
不建议这样做,因为它既危险又缓慢。
不确定您向我们展示的内容是否真的是您想要做的,但更好的方法是:
library(dplyr)
library(stringr)
my_fun <- function(data) {
data %>%
mutate_at(vars(starts_with("z")), .funs = list(TBC=~.*12)) %>%
rename_at(vars(ends_with('TBC')), .funs = ~{.x %>% str_extract('\\d') %>% str_c('X_', .)})
}
此外,由于您需要对多个数据框执行此操作,您可以使用@koenniem 建议来使用purrr::map()
. 将每个数据框放在一个列表中,并将该函数应用于列表的每个元素:
library(purrr)
df2 <- df %>% mutate_at(vars(-responseid), ~.+4)
df_t <- list(df, df2)
df_t %>%
map_df(my_fun)
#> responseid z3_1 z4_1 z5_1 X_3 X_4 X_5
#> 1 1 4.720 7.08 NA 56.640 84.96 NA
#> 2 2 1.180 NA 1.18 14.160 NA 14.16
#> 3 3 1.180 NA 1.18 14.160 NA 14.16
#> 4 4 2.596 3.54 NA 31.152 42.48 NA
#> 5 5 15.340 NA NA 184.080 NA NA
#> 6 6 2.360 NA 2.36 28.320 NA 28.32
#> 7 1 8.720 11.08 NA 104.640 132.96 NA
#> 8 2 5.180 NA 5.18 62.160 NA 62.16
#> 9 3 5.180 NA 5.18 62.160 NA 62.16
#> 10 4 6.596 7.54 NA 79.152 90.48 NA
#> 11 5 19.340 NA NA 232.080 NA NA
#> 12 6 6.360 NA 6.36 76.320 NA 76.32
推荐阅读
- node.js - 为终端设置代理,我无法使用 axios 正确重定向
- mysql - 如何将日期分组为月份并在分组后添加新列
- mongodb - 如何使 MongoDB Upsert 真正具有幂等性?
- apache-kafka - 断路器模式是否也适用于异步请求?
- python - (Django) OperationalError at / no such column: minishop_app_products.user_id
- python - 按逻辑顺序/读取方向显示 Azure OCR 输出
- flutter - 是否可以使用从 for 循环创建的单选列表图块在颤振中从构造函数中输出和选择数据
- apache-spark - pyspark.sql 分组数据是否将每个组放入单个分区?
- java - 堆中对象的内存引用是否会耗尽空间?
- excel - Excel。日期和时间 = 轮班 X