Использование функции apply для расчета в data.frame без изменения формата моего столбца даты - PullRequest
4 голосов
/ 22 сентября 2019

Это мой data.frame:

df<-structure(list(Data = structure(c(18158, 18157, 18156, 18155, 
18152), class = "Date"), A = c(19.46, 19.26, 19.43, 19.44, 
19.1), B = c(49.72, 49.2, 48.45, 47, 51.34), C = c(45.69, 
44.92, 44.12, 43.07, 43), D = c(48.32, 48.02, 47.3, 46.65, 
47.14)), row.names = c(NA, 5L), class = "data.frame")

Я хочу выполнить следующий расчет с использованием функции применения , но без извлечения Столбец даты:

new.df<-apply(df,2, function(x) (-diff(x)/x[-length(x)]))

Я не могу этого сделать, потому что есть столбец формата «Дата».Как я могу изменить свою функцию применения, чтобы справиться с ней, и результат продолжает давать кадру данных с первым столбцом все еще формат «Дата»?

1 Ответ

1 голос
/ 22 сентября 2019

Если мы знаем положение столбца «Дата», используйте метод индексации, чтобы удалить столбец

f1 <- function(x) (-diff(x)/x[-length(x)])
apply(df[-1], 2, f1)

Или, чтобы сделать его менее подверженным ошибкам, удалите столбец с помощью name

apply(df[setdiff(names(df), 'Data')], 2, f1)

apply преобразуется в matrix, а matrix может иметь только один тип.Итак, что происходит, это то, что класс Date приводится в режим целочисленного хранения, если он также включен.

Если есть столбцы character, все элементы будут преобразованы в character, и вычисление не будет работать

Функция diff возвращает вывод с lengthменьше length входных данных, и если нам нужно обновить исходные столбцы набора данных, будет length несоответствие.Чтобы избежать этого, добавьте NA в начале

f2 <- function(x) (c(NA, -diff(x)/x[-length(x)]))
df[-1] <- apply(df[-1],2, f2)

Если мы создаем новые столбцы

df[paste0(names(df)[-1], "_diffs")] <- apply(df[-1],2, f2)

Или чтобы сделать его более динамичным

i1 <- sapply(df, is.numeric)
apply(df[i1], 2,  f1)

Кроме того, для наборов данных нескольких типов можно использовать lapply/sapply

lapply(df[i1], function(x) -diff(x)/x[-length(x)])

С dplyr мы можем использовать mutate_if

library(dplyr)
df %>%
   mutate_if(is.numeric, ~ c(NA_real_, diff(.)/.[-n()]))
#      Data            A           B            C            D
#1 2019-09-19           NA          NA           NA           NA
#2 2019-09-18 -0.010277492 -0.01045857 -0.016852703 -0.006208609
#3 2019-09-17  0.008826584 -0.01524390 -0.017809439 -0.014993753
#4 2019-09-16  0.000514668 -0.02992776 -0.023798731 -0.013742072
#5 2019-09-13 -0.017489712  0.09234043 -0.001625261  0.010503751

если нам нужно создать новые столбцы, поместите их в list и сделайте именование как в list

df %>%
    mutate_if(is.numeric, list(diffs = ~ c(NA_real_, diff(.)/.[-n()])))
#        Data     A     B     C     D      A_diffs     B_diffs      C_diffs      D_diffs
#1 2019-09-19 19.46 49.72 45.69 48.32           NA          NA           NA           NA
#2 2019-09-18 19.26 49.20 44.92 48.02 -0.010277492 -0.01045857 -0.016852703 -0.006208609
#3 2019-09-17 19.43 48.45 44.12 47.30  0.008826584 -0.01524390 -0.017809439 -0.014993753
#4 2019-09-16 19.44 47.00 43.07 46.65  0.000514668 -0.02992776 -0.023798731 -0.013742072
#5 2019-09-13 19.10 51.34 43.00 47.14 -0.017489712  0.09234043 -0.001625261  0.010503751
...