Как рассчитать доходность в data.table? - PullRequest
0 голосов
/ 26 августа 2018

Я новичок в переполнении стека и начинающий R.

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

Date        C1  C2  C3
31.01.1985  NA  47  NA
28.02.1985  NA  45  NA
29.03.1985  130 56  NA
30.04.1985  140 67  NA
31.05.1985  150 48  93
28.06.1985  160 79  96
31.07.1985  160 56  94
30.08.1985  160 77  93
30.09.1985  160 66  93
31.10.1985  160 44  93
29.11.1985  160 55  93

Это data.tableФормат, скажем, называется «Цены», столбцы - это компании, значения - это цены, в реальном наборе данных много столбцов и строк.Я хочу построить новый DT, в котором я рассчитываю ежемесячные доходы, я знаю, что вы можете сделать это с помощью функции diff().но как мне построить мою новую таблицу данных с таким количеством столбцов без циклов for?

Я думал о:

Returns <- diff(Prices[, names(Prices) != "Date"])

, но это по какой-то причине только выдает:

[1] 1 0 0

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

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Я бы написал функцию для работы с одним столбцом значений

pc.change <- function(x) {   
(c(x[2:length(x)], NA) - x)*100/x }

И затем применил бы это к матрице всех столбцов значений

d <- read.table(text = "Date        C1  C2  C3
31.01.1985  NA  47  NA
28.02.1985  NA  45  NA
29.03.1985  130 56  NA
30.04.1985  140 67  NA
31.05.1985  150 48  93
28.06.1985  160 79  96
31.07.1985  160 56  94
30.08.1985  160 77  93
30.09.1985  160 66  93
31.10.1985  160 44  93
29.11.1985  160 55  93", header = TRUE)

apply(as.matrix(d[,2:4]), 2, pc.change)

Это дает мне

            C1         C2        C3
[1,]       NA  -4.255319        NA
[2,]       NA  24.444444        NA
[3,] 7.692308  19.642857        NA
[4,] 7.142857 -28.358209        NA
[5,] 6.666667  64.583333  3.225806
[6,] 0.000000 -29.113924 -2.083333
[7,] 0.000000  37.500000 -1.063830
[8,] 0.000000 -14.285714  0.000000
[9,] 0.000000 -33.333333  0.000000
[10,] 0.000000  25.000000  0.000000
[11,]       NA         NA        NA

После этого можно будет преобразовать это в таблицу данных, если необходимо

0 голосов
/ 26 августа 2018

Причина, по которой вы получаете эти выходные данные, в том, что Prices[, names(Prices) != "Date"] возвращает логический вектор:

> Prices[, names(Prices) != "Date"]
[1] FALSE  TRUE  TRUE  TRUE

И поскольку вы можете выполнять вычисления с помощью логики, вы также можете использовать diff для логического вектора.FALSE затем обрабатывается как 0, а TRUE как 1.Итак, в основном вы делали diff(c(0,1,1,1)).


Возможное решение для того, что вы хотите:

cols <- setdiff(names(Prices),"Date")

# option 1:
Prices[, paste0(cols,"_return") := lapply(.SD, function(x) (x - shift(x, fill = NA))/shift(x, fill = NA)), .SDcols = cols][]

# option 2:
Prices[, paste0(cols,"_return") := lapply(.SD, function(x) c(NA,diff(x))/shift(x, fill = NA)), .SDcols = cols][]

, что дает:

> Prices
          Date  C1 C2 C3  C1_return   C2_return   C3_return
 1: 1985-01-31  NA 47 NA         NA          NA          NA
 2: 1985-02-28  NA 45 NA         NA -0.04255319          NA
 3: 1985-03-29 130 56 NA         NA  0.24444444          NA
 4: 1985-04-30 140 67 NA 0.07692308  0.19642857          NA
 5: 1985-05-31 150 48 93 0.07142857 -0.28358209          NA
 6: 1985-06-28 160 79 96 0.06666667  0.64583333  0.03225806
 7: 1985-07-31 160 56 94 0.00000000 -0.29113924 -0.02083333
 8: 1985-08-30 160 77 93 0.00000000  0.37500000 -0.01063830
 9: 1985-09-30 160 66 93 0.00000000 -0.14285714  0.00000000
10: 1985-10-31 160 44 93 0.00000000 -0.33333333  0.00000000
11: 1985-11-29 160 55 93 0.00000000  0.25000000  0.00000000

Если вы хотите создать новый data.table, вы можете использовать один из следующих двух вариантов:

# option 1:
Returns <- Prices[, c(list(Date = Date), lapply(.SD, function(x) (x - shift(x, fill = NA))/shift(x, fill = NA))), .SDcols = cols]

# option 2:
Returns <- copy(Prices)
Returns[, (cols) := lapply(.SD, function(x) (x - shift(x, fill = NA))/shift(x, fill = NA)), .SDcols = cols]

Используемые данные:

Prices <- fread("Date        C1  C2  C3
31.01.1985  NA  47  NA
28.02.1985  NA  45  NA
29.03.1985  130 56  NA
30.04.1985  140 67  NA
31.05.1985  150 48  93
28.06.1985  160 79  96
31.07.1985  160 56  94
30.08.1985  160 77  93
30.09.1985  160 66  93
31.10.1985  160 44  93
29.11.1985  160 55  93")[, Date := as.Date(Date, "%d.%m.%Y")]
...