2016-08-18 46 views
1

我有一个可以用for循环轻松解决的问题。但是,由于我在数据框中有成千上万行,因此需要很长的计算时间,因此我正在寻找一种快速而智能的解决方案。对于每一行提取列名中与单元格中的其他值匹配的值

对于我的数据帧的每一行,我要粘贴单元格的其列名称匹配从第一列的一个(INDEX)

数据框看起来像这样

> mydata 
    INDEX 1 2 3 4 5 6 
1  2 18.9 9.5 22.6 4.7 16.2 7.4 
2  2 18.9 9.5 22.6 4.7 16.2 7.4 
3  2 18.9 9.5 22.6 4.7 16.2 7.4 
4  4 18.9 9.5 22.6 4.7 16.2 7.4 
5  4 18.9 9.5 22.6 4.7 16.2 7.4 
6  5 18.9 9.5 22.6 4.7 16.2 7.4 

值下面是重现它的代码:

mydata <- data.frame(INDEX=c(2,2,2,4,4,5), ONE=(rep(18.9,6)), TWO=(rep(9.5,6)), 
        THREE=(rep(22.6,6)), FOUR=(rep(4.7,6)), FIVE=(rep(16.2,6)), SIX=(rep(7.4,6))) 
colnames(mydata) <- c("INDEX",1,2,3,4,5,6) 

这是用新计算变量的新数据框中:

> new_mydf 
    INDEX 1 2 3 4 5 6 VARIABLE 
3  2 18.9 9.5 22.6 4.7 16.2 7.4  9.5 
2  2 18.9 9.5 22.6 4.7 16.2 7.4  9.5 
1  2 18.9 9.5 22.6 4.7 16.2 7.4  9.5 
5  4 18.9 9.5 22.6 4.7 16.2 7.4  4.7 
4  4 18.9 9.5 22.6 4.7 16.2 7.4  4.7 
6  5 18.9 9.5 22.6 4.7 16.2 7.4  16.2 

我使用下面的for循环解决了它,但是,正如我上面写的,我正在寻找更直接的解决方案(可能使用像dplyr或其他函数的包?),因为循环是慢我的扩展数据集

id = mydata$INDEX 
new_mydf <- data.frame() 
for (i in 1:length(id)) { 
    mydata_row <- mydata[i,] 
    value <- mydata_row$INDEX 
    mydata_row["VARIABLE"] <- mydata_row[,names(mydata_row) == value] 
    new_mydf <- rbind(mydata_row,new_mydf) 
} 
new_mydf <- new_mydf[ order(new_mydf[,1]), ] 
+0

随着data.table,有这样的: http://stackoverflow.com/q/33310179/ – Frank

+0

谢谢,解决方案与data.table工作良好! – refroll

回答

1

根据您的循环,这用apply与匿名函数可能会快一些(与你的mydata初始定义):

mydata$VARIABLE<-apply(mydata, 1, function(x) { x[names(x)==x[names(x)=="INDEX"]] }) 

编辑:和它的作品,即使INDEX字符:

mydata <- data.frame(INDEX=c("B","B","B","D","D","E"), "A"=(rep(18.9,6)), "B"=(rep(9.5,6)), 
       "C"=(rep(22.6,6)), "D"=(rep(4.7,6)), "E"=(rep(16.2,6)), "F"=(rep(7.4,6))) 

mydata$VARIABLE<-apply(mydata, 1, function(x) { x[names(x)==x[names(x)=="INDEX"]] }) 

> mydata INDEX A B C D E F VARIABLE 1 B 18.9 9.5 22.6 4.7 16.2 7.4 9.5 2 B 18.9 9.5 22.6 4.7 16.2 7.4 9.5 3 B 18.9 9.5 22.6 4.7 16.2 7.4 9.5 4 D 18.9 9.5 22.6 4.7 16.2 7.4 4.7 5 D 18.9 9.5 22.6 4.7 16.2 7.4 4.7 6 E 18.9 9.5 22.6 4.7 16.2 7.4 16.2

+0

谢谢,这个解决方案效果很好。但是,在我原来的扩展数据框中,我必须使用字符而不是“1”,“2”等来重命名列, – refroll

+0

不客气。乐意帮助你! @aichao子集解决方案非常棒,速度非常快!如果你有一个非常大的数据集,它可能会更好用,而且我认为它可以很容易地适用于字符索引(使用因子(INDEX)?) – Toshiro

+0

@Toshiro:我用'match'更新了答案以匹配将'INDEX'中的数据添加到列名中。 – aichao

1

你想要什么可以通过以下方式实现:

new_mydf <- data.frame(mydata, 
         VARIABLE=mydata[cbind(seq_len(nrow(mydata)), 
              match(as.character(mydata$INDEX),colnames(mydata)))]) 

这使用子集与指数,这将是比apply更快。例如,如果你的数据集是:

INDEX Alpha Beta Charlie Delta Epsilon Foxtrot 
1 Beta 18.9 9.5 22.6 4.7 16.2  7.4 
2 Beta 18.9 9.5 22.6 4.7 16.2  7.4 
3 Beta 18.9 9.5 22.6 4.7 16.2  7.4 
4 Delta 18.9 9.5 22.6 4.7 16.2  7.4 
5 Delta 18.9 9.5 22.6 4.7 16.2  7.4 
6 Epsilon 18.9 9.5 22.6 4.7 16.2  7.4 

这将给:

INDEX Alpha Beta Charlie Delta Epsilon Foxtrot VARIABLE 
1 Beta 18.9 9.5 22.6 4.7 16.2  7.4  9.5 
2 Beta 18.9 9.5 22.6 4.7 16.2  7.4  9.5 
3 Beta 18.9 9.5 22.6 4.7 16.2  7.4  9.5 
4 Delta 18.9 9.5 22.6 4.7 16.2  7.4  4.7 
5 Delta 18.9 9.5 22.6 4.7 16.2  7.4  4.7 
6 Epsilon 18.9 9.5 22.6 4.7 16.2  7.4  16.2 

为基准,模拟一个更大的数据集:

## simulate some data with 1000 columns and 1000 rows 
INDEX <- ceiling(runif(1000,0,1000)) 
data <- rep(runif(1000,0,1), each=1000) 
mydata <- data.frame(INDEX=INDEX,matrix(data,nrow=1000)) 
colnames(mydata) <- c("INDEX", seq_len(1000)) 

## using indexing 
system.time(new_mydf <- data.frame(mydata, VARIABLE=mydata[cbind(seq_len(nrow(mydata)),match(as.character(mydata$INDEX),colnames(mydata)))])) 
## user system elapsed 
## 0.030 0.001 0.031 

## using apply 
system.time(mydata$VARIABLE<-apply(mydata, 1, function(x) { x[names(x)==x[names(x)=="INDEX"]] })) 
## user system elapsed 
## 0.268 0.010 0.291 

## check that we computed the same thing 
all.equal(mydata,new_mydf,check.names=FALSE) 
##[1] TRUE 
相关问题