Перебирать строки и переменные с одинаковым префиксом - PullRequest
3 голосов
/ 03 июня 2019

Предположим, у нас есть следующие данные:

d <- data.frame(
  "V" = c("A", "B"),
  "X1" = c("A", "A"),
  "X2" = c("B","B"),
  "X3" = c("C", "C"),
  "Y1" = c(1, 4),
  "Y2" = c(2, 5),
  "Y3" = c(3, 6)
)
d[] <- lapply(d, as.character)

d
  V X1 X2 X3 Y1 Y2 Y3
1 A  A  B  C  1  2  3
2 B  A  B  C  4  5  6

Я хочу создать переменную VAL, которая будет принимать значение Y [n], если V = X [n]

Я могу сделать это с помощью операторов ifelse, но я хочу избежать вложенного ifelse, потому что n неизвестно

d$VAL_ifelse = ifelse(d$V == d$X1,d$Y1,
                      ifelse(d$V == d$X2,d$Y2,
                             ifelse(d$V == d$X3,d$Y3,NA)))  

Я пытался создать этот цикл, но проблема в j, я думаю?

d_X_var=grep("^X", names(d), value=TRUE)

for(i in 1:nrow(d)){
  for(j in 1:length(d_X_var)){
    if((d[i,c('V')] == d[i,paste0('X',j)]) == TRUE){
      d$VAL_loop[i] <- as.character(d[i,paste0('Y',j)])
    } else if((d[i,c('V')] != d[i,paste0('X',j)]) == TRUE){
      d$VAL_loop[i] <- NA
    }
  }
}

d
  V X1 X2 X3 Y1 Y2 Y3 VAL_ifelse VAL_loop
1 A  A  B  C  1  2  3          1     <NA>
2 B  A  B  C  4  5  6          5     <NA>

Ответы [ 3 ]

4 голосов
/ 03 июня 2019

Мы можем использовать векторизованный способ, чтобы получить VAL

d$Val <- d[5:7][which(d[2:4] == d$V, arr.ind = TRUE)]

d
#  V X1 X2 X3 Y1 Y2 Y3 Val
#1 A  A  B  C  1  2  3   1
#2 B  A  B  C  4  5  6   5

Вышесказанное верно, если вы заранее знаете номера столбцов X и Y. Если вы не знаете, мы можем сначала использовать grep, чтобы получить номера столбцов, а затем подмножество.

X_cols <- grep("^X", names(d))
Y_cols <- grep("^Y", names(d))
d$Val <- d[Y_cols][which(d[X_cols] == d$V, arr.ind = TRUE)]
0 голосов
/ 03 июня 2019

Вот немного запутанный способ использования ifelse и diag:

d$Val <- ifelse(d$V == diag(as.matrix(d[,2:4])), diag(as.matrix(d[,5:7])), NA) 

Выход:

  V X1 X2 X3 Y1 Y2 Y3 Val
1 A  A  B  C  1  2  3   1
2 B  A  B  C  4  5  6   5
0 голосов
/ 03 июня 2019

Мы можем использовать max.col из base R в векторизованном виде

d$Val <- d[5:7][cbind(seq_len(nrow(d)), max.col(d$V == d[2:4], 'first'))]
d
#   V X1 X2 X3 Y1 Y2 Y3 Val
#1 A  A  B  C  1  2  3   1
#2 B  A  B  C  4  5  6   5

Обновить

Если совпадений нет, мы можем получить вывод как NA с rowSums (данные из комментариев)

d <- data.frame( "V" = c("A", "B","C","D","C"), "X1" = c("A", "A","A","A","A"), "X2" = c("B","B","B","B","A"), "X3" = c("C", "C","C","D","A"), "Y1" = c(1, 4, 7, 10, 13), "Y2" = c(2, 5, 8, 11, 14), "Y3" = c(3, 6, 9, 12,15), "Val_expected" = c(1,5,9,12,NA) ) 
d[,] <- lapply(d, as.character) 

d$Val <- d[5:7][cbind(seq_len(nrow(d)), max.col(d$V == d[2:4], 'first'))]
d$Val <- as.numeric(d$Val) * (NA^ !rowSums(d$V == d[2:4]))
d$Val
#[1]  1  5  9 12 NA
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...