我想编写一个向数据框添加新变量的函数。该新变量在与参数中传递的一组变量(作为字符串向量)对应的值的串联中构成。在基础R中,我会写一些类似的东西:
addConcatFields<-function(data,listOfVar)
{
data$uniqueId=data[,listOfVar[1]]
for(elt in listOfVar[2:length(listOfVar)])
{
data$uniqueId=paste(data$uniqueId,data[,elt],sep='_')
}
return(data)
}
addConcatFields(iris,c('Petal.Width','Species'))
# gives:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species uniqueId
1 5.1 3.5 1.4 0.2 setosa 0.2_setosa
2 4.9 3.0 1.4 0.2 setosa 0.2_setosa
...
我最初的目标是使用dplyr :: mutate,尽管我阅读了编程小插图http://127.0.0.1:31671/library/dplyr/doc/programming.html,但我没有达到目标。因为我想了解我错过的观点,我想用mutate解决问题,我会很感激建议。
答案 0 :(得分:1)
解决这个问题的最佳方法是使用准引用 - 本文非常有助于解释基本原理。
https://dplyr.tidyverse.org/articles/programming.html
不是将列名存储为字符串,最好的选择是将它们存储为带引号的字符串,因此:
varlist <- rlang::quos('Petal.Width', 'Species')
该行为您提供了2个排序列表 - 一个包含Petal.Width列和一个Species列。
然后你想用!!!将命令列表附加到dplyr语句(!!!因为您正在拼接多条指令)。
dplyr::select(iris, !!! varlist)
应该给你想要的结果。
答案 1 :(得分:0)
使用数据表,我会做这样的事情
library(data.table)
iris <- data.table(iris)
iris[, uniqueId := do.call(function(...) paste(..., sep = "_"),.SD), .SDcols = c('Petal.Width','Species')]
答案 2 :(得分:0)
查看unite
here中的tidyr
功能。它是tidyverse
包含dplyr
的同一组包的一部分。
library(tidyr)
unite(iris,uniqueID,c(Petal.Width,Species))
# Sepal.Length Sepal.Width Petal.Length uniqueID
#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
如果您不想丢失连接的两列,请添加remove = F
unite(iris,uniqueID,c(Petal.Width,Species),remove = F)
# Sepal.Length Sepal.Width Petal.Length uniqueID Petal.Width Species
#1 5.1 3.5 1.4 0.2_setosa 0.2 setosa
#2 4.9 3.0 1.4 0.2_setosa 0.2 setosa
#3 4.7 3.2 1.3 0.2_setosa 0.2 setosa
#4 4.6 3.1 1.5 0.2_setosa 0.2 setosa
答案 3 :(得分:0)
要添加到其他答案,因为您说要使用dplyr的mutate
来执行此操作。
以下是mutate
中使用paste
:
iris %>% mutate(uniqueId= paste(Petal.Width, Species, sep = '_'))
# gives the following result:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species uniqueId
1 5.1 3.5 1.4 0.2 setosa 0.2_setosa
2 4.9 3 1.4 0.2 setosa 0.2_setosa
3 4.7 3.2 1.3 0.2 setosa 0.2_setosa
4 4.6 3.1 1.5 0.2 setosa 0.2_setosa
5 5 3.6 1.4 0.2 setosa 0.2_setosa
6 5.4 3.9 1.7 0.4 setosa 0.4_setosa
7 4.6 3.4 1.4 0.3 setosa 0.3_setosa
8 5 3.4 1.5 0.2 setosa 0.2_setosa
9 4.4 2.9 1.4 0.2 setosa 0.2_setosa
10 4.9 3.1 1.5 0.1 setosa 0.1_setosa
...
如果您的功能是自定义功能,您可以对其进行矢量化然后再使用它。 例如,这导致与上面相同的结果:
concat_fields<-function(var1, var2) {
return (paste(var1, var2, sep = '_'))
}
v_concat_fields <- Vectorize(concat_fields)
iris %>% mutate(v_concat_fields(Petal.Width, Species))
进入mutate的函数将应用于数据框的列,它具有类型为矢量的参数,而不是数据帧。
答案 4 :(得分:0)
好的,在这里考虑过它是另一种解决方案。
使用匹配函数将字符串名称转换为列号。
然后使用像这样的列号(将示例中的数字向量替换为匹配结果):
df <- tbl_df(df[c(3, 4, 7, 1, 9, 8, 5, 2, 6, 10)])
这样做的好处是,如果匹配返回任何不正确的值,您可以使用错误中止该函数。