R: рассчитать децильные ранги по группам - PullRequest
1 голос
/ 23 мая 2019

У меня есть фрейм данных crsppofo, который содержит ежемесячные финансовые данные с несколькими переменными. Для моего вопроса важны следующие вопросы:

   PERMNO monthyear BetaShr
1:  85814 199501    0.5
2:  12345 199501    1.0
3:  85814 200002    1.5
4:  56789 200002    2.0
5:  12345 200002    2.5

"PERMNO" описывает каждую отдельную акцию, "monthyear" явно показывает год и месяц, а "BetaShr" - это мой показатель риска, отсортированный по возрастанию.

Что я пытаюсь сделать, так это назначить децильные ранги (от 1 до 10) в соответствии с "BetaShr", но сгруппированные по "monthyear". Самый низкий ранг в децилях должен присваиваться самым низким 10% от "BetaShr" каждого месяца. Результат должен выглядеть следующим образом:

   PERMNO monthyear BetaShr BetaDecileRank
1:  85814 199501    0.5     1
2:  12345 199501    1.0     10
3:  85814 200002    1.5     1
4:  56789 200002    2.0     5
5:  12345 200002    2.5     10

Конечно, это просто упрощенный пример, в котором назначено только три дециля, чтобы дать вам пример моего желаемого результата (предполагая диапазон "BetaShr" между 0,5 и 1,0 для 199501 и диапазон от 1,5 до 2,5 для 200002) , Вы поняли.

Благодаря исследованиям я придумал этот код:

library(purrr)
library(StatMeasures)
library(dplyr)
crsppofo <- crsppofo %>%
  split(crsppofo$monthyear) %>%
  map_df(~ mutate(., BetaDecileRank = decile(crsppofo$BetaShr)))

, приводящий к ошибке:

Error: Column `BetaDecileRank` must be length 2524 (the group size) or one, not 896935

Любая помощь по этой проблеме будет принята с благодарностью. Не стесняйтесь улучшать мой код или предлагать совершенно другой подход. Если вам нужна дополнительная информация, дайте мне знать через комментарии. Я также открыт для улучшений, касающихся моего вопроса и моего присутствия в SO, так как я только новичок на этом форуме и в R.

1 Ответ

1 голос
/ 23 мая 2019

Проблема в том, что внутри группы split decile применяется ко всему столбцу набора данных 'BetaShr' вместо строк из этого разделенного набора данных

... %>%
    map_df(~ mutate(., BetaDecileRank = decile(crsppofo$BetaShr)))
                                               ^^^^

Это должно быть

decile(.$BetaShr)

-fullcode

library(dplyr)
library(purrr)
library(StatMeasures)
crsppofo <- crsppofo %>%
              split(crsppofo$monthyear) %>%
              map_df(~ mutate(., BetaDecileRank = decile(.$BetaShr)))
crsppofo
#  PERMNO monthyear BetaShr BetaDecileRank
#1  85814    199501     0.5              1
#2  12345    199501     1.0             10
#3  85814    200002     1.5              1
#4  56789    200002     2.0              5
#5  12345    200002     2.5             10

Обратите внимание, что нам не нужно split, а затем выполнить цикл с использованием map.Вместо этого это можно сделать с помощью опции group_by/mutate

crsppofo %>% 
   group_by(monthyear) %>% 
   mutate(BetaDecileRank = decile(BetaShr))
# A tibble: 5 x 4
# Groups:   monthyear [2]
#  PERMNO monthyear BetaShr BetaDecileRank
#   <int>     <int>   <dbl>          <int>
#1  85814    199501     0.5              1
#2  12345    199501     1               10
#3  85814    200002     1.5              1
#4  56789    200002     2                5
#5  12345    200002     2.5             10

data

crsppofo <- structure(list(PERMNO = c(85814L, 12345L, 85814L, 56789L, 12345L
), monthyear = c(199501L, 199501L, 200002L, 200002L, 200002L), 
    BetaShr = c(0.5, 1, 1.5, 2, 2.5)), class = "data.frame",
    row.names = c("1:", 
"2:", "3:", "4:", "5:"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...