Reputation: 3082
I have a data.frame
as follow,
A <- sample(1:10,5)
B <- sample(11:20, 5)
C <- sample(21:30, 5)
index <- sample(1:3,5, replace=TRUE)
data <- data.frame(A,B,C,index)
> data
A B C index
1 9 17 30 3
2 10 15 26 2
3 2 19 23 2
4 3 13 29 2
5 8 12 25 2
my desired output would be
> data$output <- c(30,15,19,13,12)
> data
A B C index output
1 9 17 30 3 30
2 10 15 26 2 15
3 2 19 23 2 19
4 3 13 29 2 13
5 8 12 25 2 12
The idea is that index indicate the number of column i would like to extract. for example for second row, index is 2, then output should be B:15.
Upvotes: 1
Views: 73
Reputation: 92302
data.table
approach (should be more efficient)
library(data.table)
setDT(data)[, output := .SD[, index, with = F], by = index]
# A B C index output
# 1: 9 17 30 3 30
# 2: 10 15 26 2 15
# 3: 2 19 23 2 19
# 4: 3 13 29 2 13
# 5: 8 12 25 2 12
Upvotes: 1
Reputation: 887501
Or,
data$output <- t(data[,-4])[data$index+(0:4)*3] #0:4 denotes 1-(1:nrow(data));
#3 is ncol(data[,-4])
data$output
#[1] 30 15 19 13 12
Upvotes: 0
Reputation:
A neat trick to avoid using, e.g., a loop, is to use a matrix to subset the data frame. Let's first generate a matrix, which specifies the 'cells' to be extracted:
m<-matrix(ncol=2, data=c(as.numeric(rownames(data)), data$index))
Now matrix m has to columns, the first for the row index and second for the column index of the data frame. Note that you might need to adjust the as.numeric(rownames(data))
part accordingly, if your row names are not in ascending order. But this solution works for the example data.
Then subsetting the data frame using this matrix simply as:
data[m]
should yield the correct result. You can then assign it to the data frame an output column:
data$output<-data[m]
This is documented in the help file for the [ operator. See ?"["
and spefically the note "When indexing arrays by [ a single argument i can be a matrix with as many columns as there are dimensions of x; the result is then a vector with elements corresponding to the sets of indices in each row of i.".
Upvotes: 1