2015-08-08 5 views
1

Как использовать одну переменную в data.frame для ссылки на другую?Использование столбца в data.frame для выбора другого

говорят, у меня есть:

col  col1  col2 
"col1" 1  5 
"col2" 2  6 
"col1" 3  7 
"col2" 4  8 

и я хочу:

col  col1  col2  answer 
"col1" 1  5   1 
"col2" 2  6   6 
"col1" 3  7   3 
"col2" 4  8   8 

,

df$answer = df[,df$col] 

не работает, и цикл принимает навсегда.

+0

Как я s 'answer' определен? – vaettchen

+0

Это число, которое находится в столбце, заданном df $ col – OldMcFartigan

+0

df $ answer = unlist (lapply (1: (dim (df) [1]), function (idx) df [idx, df [, df $ col [idx]])), похоже, работает, но может быть, что-то лучше? – OldMcFartigan

ответ

3

Я знаю, что уже ответил, но я думал, что другой подход может быть полезен:

read.table(text='col  col1  col2 
"col1" 1  5 
"col2" 2  6 
"col1" 3  7 
"col2" 4  8',h=T)->df 

df$answer <- as.integer(df[ cbind(c(1:nrow(df)), match(df$col, names(df))) ]) 
df 
# col col1 col2 answer 
# 1 col1 1 5  1 
# 2 col2 2 6  6 
# 3 col1 3 7  3 
# 4 col2 4 8  8 
+0

Это идиоматический ответ R в основном. –

3

Это не выглядит очень сложно, но решение, которое я нашел, не очень изящно, возможно, есть лучшие способы. Но вы можете использовать match и затем подмножество в соответствии с матча:

dat <- read.table(text="col  col1  col2 
col1 1  5 
col2 2  6 
col1 3  7 
col2 4  8", header = T, stringsAsFactors = FALSE) 

cols <- unique(dat$col) 
matches <- match(dat$col, cols) 

dat$answer <- sapply(seq_along(matches), function (i) { 
    dat[i,cols[matches[i]]] 
}) 

И результат:

> dat 
    col col1 col2 answer 
1 col1 1 5  1 
2 col2 2 6  6 
3 col1 3 7  3 
4 col2 4 8  8 

Edit

На самом деле, вот уже гораздо лучший подход:

dat$answer <- sapply(1:nrow(dat), function(r) { 
    dat[r,dat$col[r]] 
}) 

Это, по-видимому, то, что вы пробовали, но используя sapply вместо unlist(lapply, так что да, не уверен, что это поможет.

1

В этом случае только с 2 столбцами ifelse может быть самым быстрым и самым простым решением.

df$answer <- ifelse(df[,1] == "col1",df[,"col1"],df[,"col2”]) 

     col col1 col2 answer 
1 col1 1 5  1 
2 col2 2 6  6 
3 col1 3 7  3 
4 col2 4 8  8 

Дополнение как N8TRO в своем комментарии для более общего решения. Простой switch может быть все, что необходимо:

for(i in 1:nrow(df)) df$ans[i] <- switch(df[i,1],df[i,df[i,1]]) 

или без "для" цикла:

df$ans <- sapply(1:nrow(df),function(i) switch(df[i,1],df[i,df[i,1]])) 

пример:

df <- data.frame(col=sample(paste0('col',1:5),10,replace=T),col1=1:10,col2=11:20,col3=21:30,col4=31:40,col5=41:50,stringsAsFactors = F) 

выбрать элементы:

df$ans <- sapply(1:nrow(df),function(i) switch(df[i,1],df[i,df[i,1]])) 

df 
    col col1 col2 col3 col4 col5 ans 
1 col1 1 11 21 31 41 1 
2 col1 2 12 22 32 42 2 
3 col5 3 13 23 33 43 43 
4 col2 4 14 24 34 44 14 
5 col3 5 15 25 35 45 25 
6 col4 6 16 26 36 46 36 
7 col5 7 17 27 37 47 47 
8 col3 8 18 28 38 48 28 
9 col1 9 19 29 39 49 9 
10 col5 10 20 30 40 50 50 
+0

Я бы поднял, но что, если есть 'col3'? – N8TRO

+0

@ N8TRO, посмотрите на мое редактирование для более общего решения. – hvollmeier

+0

Мне это нравится. Switch - очень мощная функция и отличная альтернатива другим двум ответам. – N8TRO

Смежные вопросы