#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"