Лучший способ применить эту функцию к каждой строке фрейма данных?

#r

#r

Вопрос:

Я хотел бы применить функцию к каждой строке фрейма данных, как показано ниже. Я знаю, как использовать apply в случае, когда фрейм данных содержит только числа, но что, если строки содержат, скажем, логические значения, строки и целые числа? Пример:

 df <- data.frame(x=1:10,
                 y=c(TRUE, FALSE),
                 z=letters[1:10],
                 stringsAsFactors=FALSE)

RowFunction <- function(row) {
  if (row$y) return(row$x)
  return (row$z)
}

sapply(1:dim(df)[1], function(i) { RowFunction(df[i, ]) })
  

Есть ли лучший способ сделать это? Моей первой мыслью было использовать функцию apply(df, 1, RowFunction) after adding row <- as.list(row) в начало строки, но это не работает, потому что apply принудительно помещает df в массив, который не может обрабатывать строки, содержащие разные типы данных.

Просто для моих R-знаний, я хотел бы знать, есть ли более чистый способ сделать это, чем sapply(1:dim(df)[1], ... ) . Есть идеи?

Заранее спасибо!

Комментарии:

1. Я хотел бы отметить, что все элементы в векторе будут иметь одинаковый режим. Единственный способ получить результаты, которые различаются по режиму или типу, — это вернуть список.

Ответ №1:

В этом случае вы можете просто использовать ifelse :

 sapply(1:dim(df)[1], function(i) { RowFunction(df[i, ]) })
 [1] "1" "b" "3" "d" "5" "f" "7" "h" "9" "j"

with(df, ifelse(y, x, z))
 [1] "1" "b" "3" "d" "5" "f" "7" "h" "9" "j"
  

Для удобства и удобочитаемости я также использовал with — это позволяет ссылаться на столбец просто по имени, без использования $ оператора.

Комментарии:

1. 2, если бы я мог для ifelse и with … 2 моих любимых!

Ответ №2:

ifelse Функция может сделать это с помощью lapply :

  lapply(df$y, ifelse, df$x, df$z)  # does return list with varying modes
  

Моя более ранняя (более неуклюжая) версия:

  res <- list()
 for(i in seq_along(rownames(df) ) ) { res <- c(res, df[i,1 2*!df[i,"y"] ]) }
 res
#--------
[[1]]
[1] 1

[[2]]
[1] "b"

[[3]]
[1] 3

[[4]]
[1] "d"

[[5]]
[1] 5

[[6]]
[1] "f"

[[7]]
[1] 7

[[8]]
[1] "h"

[[9]]
[1] 9

[[10]]
[1] "j"