如何动态“改变”R中的数据帧?

时间:2016-03-05 07:59:28

标签: r loops dplyr

假设我想记录数据框中的转换列,比如iris数据,并为每个所需的列动态创建带有后缀_log的新列。

我想要实现的目标是:

df$Sepal.Length_log <- log (df$Sepal.Length)
df$Sepal.Width_log <- log (df$Sepal.Width)
df$Petal.Length_log <- log (df$Petal.Length)
df$Sepal.Width_log <- log (df$Sepal.Width)  

但是当你的数据有很多列需​​要转换时,这将是一项繁琐的工作,所以我想使用mutate包的循环和dplyr函数动态实现这一点,我的失败天真的审判是:

library (dplyr)
data(iris)
varLabel <- c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width')
for (i in 1:length (varLabel)) {
  varNew <- paste (varLabel[i],'log',sep='_')
  iris <- dplyr::mutate (iris,varNew=log (varLabel[i])) # problem arises here
}

我收到此错误:Error: non-numeric argument to mathematical function

我搜索了一个解决方案,最相关的解决方案似乎是tutorial标准和非标准评估,这个postthat也是,但我不能弄清楚如何从那里借用解决方案。任何帮助将不胜感激。

注意:
我想在数据集中同时包含旧列和新列。

3 个答案:

答案 0 :(得分:4)

data.table的解决方案:

library(data.table)
data(iris)
DT <- as.data.table(iris)
varLabel <- c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width')

NewColumn <- paste0(varLabel, "_log")

DT[, (NewColumn) := lapply(.SD, log), .SDcols = varLabel]

DT
#>      Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
#>   1:          5.1         3.5          1.4         0.2    setosa
#>   2:          4.9         3.0          1.4         0.2    setosa
#>   3:          4.7         3.2          1.3         0.2    setosa
#>   4:          4.6         3.1          1.5         0.2    setosa
#>   5:          5.0         3.6          1.4         0.2    setosa
#>  ---                                                            
#> 146:          6.7         3.0          5.2         2.3 virginica
#> 147:          6.3         2.5          5.0         1.9 virginica
#> 148:          6.5         3.0          5.2         2.0 virginica
#> 149:          6.2         3.4          5.4         2.3 virginica
#> 150:          5.9         3.0          5.1         1.8 virginica
#>      Sepal.Length_log Sepal.Width_log Petal.Length_log Petal.Width_log
#>   1:         1.629241       1.2527630        0.3364722      -1.6094379
#>   2:         1.589235       1.0986123        0.3364722      -1.6094379
#>   3:         1.547563       1.1631508        0.2623643      -1.6094379
#>   4:         1.526056       1.1314021        0.4054651      -1.6094379
#>   5:         1.609438       1.2809338        0.3364722      -1.6094379
#>  ---                                                                  
#> 146:         1.902108       1.0986123        1.6486586       0.8329091
#> 147:         1.840550       0.9162907        1.6094379       0.6418539
#> 148:         1.871802       1.0986123        1.6486586       0.6931472
#> 149:         1.824549       1.2237754        1.6863990       0.8329091
#> 150:         1.774952       1.0986123        1.6292405       0.5877867

dplyrmutate_each的简短解决方案。只需使用命名向量来保留所有变量

library(dplyr)
data(iris)
varLabel <- c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width')
names(varLabel) <- paste0(varLabel,'_log')

res <- iris %>% mutate_each_(funs(log(.)), vars = varLabel)
head(res)
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa
#>   Sepal.Length_log Sepal.Width_log Petal.Length_log Petal.Width_log
#> 1         1.629241        1.252763        0.3364722      -1.6094379
#> 2         1.589235        1.098612        0.3364722      -1.6094379
#> 3         1.547563        1.163151        0.2623643      -1.6094379
#> 4         1.526056        1.131402        0.4054651      -1.6094379
#> 5         1.609438        1.280934        0.3364722      -1.6094379
#> 6         1.686399        1.360977        0.5306283      -0.9162907

答案 1 :(得分:4)

试试这个

float

答案 2 :(得分:2)

我们可以使用mutate_each

 nm1 <- paste0("varNew_", varLabel)
 res <- iris %>% 
           mutate_each_(funs(log(.)), varLabel) %>% 
           setNames(., c(nm1, setdiff(names(.), varLabel))) %>% 
           bind_cols(iris[intersect(names(iris), varLabel)], .)

head(res,2)
#Source: local data frame [2 x 9]

#  Sepal.Length Sepal.Width Petal.Length Petal.Width varNew_Sepal.Length varNew_Sepal.Width varNew_Petal.Length varNew_Petal.Width Species
#         (dbl)       (dbl)        (dbl)       (dbl)               (dbl)              (dbl)               (dbl)              (dbl)  (fctr)
#1          5.1         3.5          1.4         0.2            1.629241           1.252763           0.3364722          -1.609438  setosa
#2          4.9         3.0          1.4         0.2            1.589235           1.098612           0.3364722          -1.609438  setosa

如果OP正在寻找base R解决方案,这也可行

iris[nm1] <- log(iris[varLabel])
head(iris,2)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species varNew_Sepal.Length
#1          5.1         3.5          1.4         0.2  setosa            1.629241
#2          4.9         3.0          1.4         0.2  setosa            1.589235
#  varNew_Sepal.Width varNew_Petal.Length varNew_Petal.Width
#1           1.252763           0.3364722          -1.609438
#2           1.098612           0.3364722          -1.609438