Как посчитать количество отрицательных значений для каждого наблюдения определенной переменной - PullRequest
0 голосов
/ 30 июня 2019

Я хочу рассчитать общее количество отрицательных значений для каждого наблюдения, используя предыдущие 10 наблюдений. Я использовал следующий код, но он не работает -

funda_addit <- funda_addit %>% 
  group_by(TICKER) %>%
  arrange(year) %>% 
  mutate(NEG_EARN = rollapply(ni, 10, sum (ni<0), partial=TRUE)) %>% 
  ungroup()

На самом деле я хочу создать новую переменную "NEG_EARN", которая представляет собой число отрицательных значений предыдущих 10 наблюдений (10 лет в моих данных) для переменной "ni". Я также использую следующий код, но он не работает -

funda_addit <- funda_addit %>% 
  group_by(TICKER) %>%
  arrange(year) %>% 
  mutate(NEG_EARN = rollapply(ni, 10, length(which(ni<0)), partial=TRUE)) %>% 
  ungroup()

Ответы [ 2 ]

2 голосов
/ 30 июня 2019

Вы можете создать вектор cumsum(ni < 0), а затем вычесть из него отсроченную версию этого вектора

funda_addit %>% 
  group_by(TICKER) %>% 
  arrange(year) %>% 
  mutate(neg_earn = {cs <- cumsum(ni < 0)
                     cs - lag(cs, 10, default = 0)})

Это эквивалентно ответу akrun, если вы измените rollapply на rollapplyr (протестировано с использованием данных примера akrun)

use_cumsum <- 
  funda_addit %>% 
    group_by(TICKER) %>% 
    arrange(year) %>% 
    mutate(neg_earn = {cs <- cumsum(ni < 0)
                       cs - lag(cs, 10, default = 0)})

use_rollapply <- 
  funda_addit %>% 
    group_by(TICKER) %>% 
    arrange(year) %>% 
    mutate(neg_earn = rollapplyr(ni, 10, FUN = f1, partial=TRUE))

all(use_cumsum == use_rollapply)
# [1] TRUE
1 голос
/ 30 июня 2019

Мы можем использовать анонимный вызов функции (или создать новую функцию) вместо целого столбца 'ni'

library(dplyr)
library(zoo)
f1 <- function(x) sum(x < 0)
funda_addit %>% 
  group_by(TICKER) %>%
  arrange(year) %>% 
  mutate(NEG_EARN = rollapplyr(ni, 10, FUN = f1, partial=TRUE)) %>% 
  ungroup()

РЕДАКТИРОВАТЬ: изменено rollapply на rollapplyr (на основе комментариев от @IceCreamToucan)

данные

set.seed(24)
funda_addit <- data.frame(TICKER = rep(LETTERS[1:3], each = 20), 
      year = 1921:1940, ni = rnorm(60))
...