我正在使用具有类似命名列的data.frame
。表单有三个版本,版本被添加到列名的末尾,所以df看起来像这样:
var1 var2 var1x var2x var1y var2z
1 2 NA NA NA NA
NA NA 1 2 NA NA
NA NA 1 3 NA NA
4 NA NA NA NA 7
因此,除了最后一个字母之外,还有许多列具有相同的名称。我想结合这些相似的列,以便最终得到类似的东西:
var1 var2
1 2
1 2
1 3
4 7
有什么想法吗?
编辑:任何变量都不可能有多个答案。因此,例如,如果var1是2,则var1x和var1y是构造的NA。
答案 0 :(得分:5)
var1<-rowMeans(df[,grepl("var1",names(df))],na.rm=TRUE)
var2<-rowMeans(df[,grepl("var2",names(df))],na.rm=TRUE)
cbind(var1,var2)
var1 var2
[1,] 1 2
[2,] 1 2
[3,] 1 3
[4,] 4 7
当所有人都是NA 时, rowMeans()
会给出NaN
当所有人都是NA时,
已编辑更改为rowMeans
以获取NA的新要求。 rowMeans给NaN,这是公平的,我只是认为足够接近NA。
如果你有很多关于多个版本的问题,我会用这样的东西自动完成整个过程:
list<-c("var1","var2")
get_col<-function(var){
rowMeans(df[,grepl(var,names(df))],na.rm=TRUE)
}
newdf<-data.frame(do.call(cbind,lapply(list,get_col)))
names(newdf)<-list
var1 var2
1 1 2
2 1 2
3 1 3
4 4 7
5 NaN NaN
答案 1 :(得分:5)
这是另一个想法:
library(dplyr)
df %>%
transmute(n_var1 = rowMeans(select(., starts_with("var1")), na.rm = TRUE),
n_var2 = rowMeans(select(., starts_with("var2")), na.rm = TRUE))
给出了:
# n_var1 n_var2
#1 1 2
#2 1 2
#3 1 3
#4 4 7
答案 2 :(得分:3)
不是我实际上会这样做,但这里是一个使用排序的答案(按变量的前4个字符排序,然后按实际值排序):
t(apply(DF, 1, function(x) x[order(substr(names(DF), 1, 4), x)]))[, c(1, 4)]
产地:
[,1] [,2]
[1,] 1 2
[2,] 1 2
[3,] 1 3
[4,] 4 7
对所有NA都应该是健壮的。
答案 3 :(得分:2)
另一种选择是基于列名中的公共前缀split
列,在逻辑矩阵(max.col
)上创建!is.na(x1)
的列索引,{{1使用行索引(cbind
)来获取每行的非NA元素。
1:nrow(x1)
注意:如果所有元素都是sapply(split(names(df1), sub('[^0-9]*$', '',names(df1))), function(x) {
x1 <- df1[x]
x1[cbind(1:nrow(x1), max.col(!is.na(x1)))]})
# var1 var2
#[1,] 1 2
#[2,] 1 2
#[3,] 1 3
#[4,] 4 7
,这也会返回NA
。
或使用NA
和splitstackshape
dplyr
library(dplyr)
library(splitstackshape)
add_rownames(df1) %>%
merged.stack(var.stub=c('var1', 'var2'), sep='var.stubs',
atStart=FALSE) %>%
.[, list(var1=var1[!is.na(var1)], var2=var2[!is.na(var2)])]
# var1 var2
#1: 1 2
#2: 1 2
#3: 1 3
#4: 4 7