Примените функцию к каждому столбцу data.frame и организуйте вывод
У меня есть этот вектор:
x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11)
Я использую эту функцию:
myfunction <- function(x){
n <- length(x)
fx <- numeric(n)
fx[1] <- min(x[1],0)
for(i in 2:n){fx[i] <- min(0,fx[i-1]+x[i])}
fx
x_min <-min(x)
fx_min <- min(fx)
fx_05 <- numeric(n)
fx_05[1] <- min(fx[1],0)
for (i in 2:n) {
if (sum(fx_05[i-1]+x[i])>0) {
fx_05[i] <- 0
} else if ((sum(fx_05[i-1]+x[i]))<(fx_min*0.5)) {
fx_05[i] <- (fx_min*0.5)
} else { fx_05[i] <- sum(fx_05[i-1]+x[i]) }
}
fx_05
as.data.frame(matrix(c(x, fx_05), ncol = 2 ))
}
xx <- myfunction(x)
Фрейм данных xx
является
V1 V2
1 5 0.0
2 2 0.0
3 -4 -4.0
4 -6 -8.5
5 -2 -8.s
6 1 -7.5
7 4 -3.5
8 2 -1.5
9 -3 -4.5
10 -6 -8.5
11 -1 -8.5
12 8 -0.5
13 9 0.0
14 5 0.0
15 -6 -6.0
16 -11 -8.5`
Я хотел бы применить эту функцию к data.frame:
df <- data.frame(x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11),
y <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11),
z <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11))
С помощью:
output <- myfunction(df)
Это не работает, и с помощью:
outputs <- data.frame(sapply(df, myfunction))
форма вывода data.frame неверна. Должно быть 2 столбца для каждого исходного столбца data.frame.
1 ответ
В этом случае вы хотели бы использовать lapply
, Он будет обрабатывать каждый столбец data.frame, поскольку на самом деле это список векторов равной длины, и каждый из двух столбцов будет возвращать data.frame.
x <- lapply(df, myfunction)
Также, sapply
работает просто отлично. Разница лишь в том, что в начале все выглядит иначе. Увидеть print(x)
за разницу между всеми решениями.
x <- sapply(df, myfunction)
После этого вы, вероятно, захотите снова объединить их из списка в data.frame. Вы можете сделать это с do.call
df2 <- do.call(cbind, x)
Это испортит имена столбцов. Вы можете изменить их, используя names
names(df2) <- NULL
df2
# 1 5 0.0 5 0.0 5 0.0
# 2 2 0.0 2 0.0 2 0.0
# 3 -4 -4.0 -4 -4.0 -4 -4.0
# 4 -6 -8.5 -6 -8.5 -6 -8.5
# ....
Примечание:
Если у вас нет data.frame, а матрицы в качестве входных данных, другой вариант будет apply
с MARGIN = 2
,
x <- apply(df, MARGIN = 2, myfunction)
Хотя в этом примере это также работает, вы столкнетесь с проблемами при наличии разных типов данных в ваших векторах, поскольку он преобразует data.frame в матрицу перед применением функции. Поэтому это не рекомендуется. Больше информации об этом можно найти в этом подробном и простом для понимания посте!
Дальнейшее чтение по этому вопросу:
Продвинутый R Хедли Уикхема Также ознакомьтесь с разделом о типах данных на этом сайте.
Сообщение в блоге Питера Вернера
Я высоко ценю вклад Gregor в этот пост.