#r #dataframe #filter #calculated-columns #stockquotes
#r #фрейм данных #Фильтр #вычисляемые столбцы #котировки акций
Вопрос:
У меня есть следующий набор данных, и я хочу написать код, который поможет определить, какие запасы были положительными или отрицательными последовательно. Данные будут иметь первые 3 столбца. последние 2 столбца вычисляются вручную в Excel для отображения ожидаемых результатов.
Это только образец, у меня были бы данные для более чем 200 акций и данные за несколько лет, причем все акции не торгуются каждый день.
В конце я хочу извлечь, какие акции имеют, скажем, 3 или 4 или 5 последовательных положительных или отрицательных изменений за день.
` Stocks Date Close Price Change for day Positive/Negative Count
A 11/11/2020 11
B 11/11/2020 50
C 11/11/2020 164
A 11/12/2020 19 8 1
B 11/12/2020 62 12 1
C 11/12/2020 125 -39 -1
A 11/13/2020 7 -12 -1
B 11/13/2020 63 1 2
C 11/13/2020 165 40 1
A 11/16/2020 17 10 1
B 11/16/2020 70 7 3
C 11/16/2020 170 5 2
A 11/17/2020 24 7 2
B 11/17/2020 52 -18 -1
C 11/17/2020 165 -5 -1
A 11/18/2020 31 7 3
B 11/18/2020 61 9 1
C 11/18/2020 157 -8 -2
Ответ №1:
Сложность заключается в том, чтобы иметь функцию, которая делает совокупную сумму, как положительную, так и отрицательную, сбрасывает счетчик при изменении знака и начинает подсчет с первого значения. Значение. Мне удалось сделать один, но он не очень эффективен и, вероятно, будет работать медленно с большим набором данных. Я подозреваю, что есть способ сделать лучше, хотя бы с помощью простого for
цикла на C или C .
library(tidyverse)
df <- read.table(text="Stocks Date Close_Price Change_for_day Positive/Negative_Count
A 11/11/2020 11 NA 0
B 11/11/2020 50 NA 0
C 11/11/2020 164 NA 0
A 11/12/2020 19 8 1
B 11/12/2020 62 12 1
C 11/12/2020 125 -39 -1
A 11/13/2020 7 -12 -1
B 11/13/2020 63 1 2
C 11/13/2020 165 40 1
A 11/16/2020 17 10 1
B 11/16/2020 70 7 3
C 11/16/2020 170 5 2
A 11/17/2020 24 7 2
B 11/17/2020 52 -18 -1
C 11/17/2020 165 -5 -1
A 11/18/2020 31 7 3
B 11/18/2020 61 9 1
C 11/18/2020 157 -8 -2",
header = TRUE) %>%
select(1:3) %>%
as_tibble()
# this formulation could be faster on data with longer stretches
nb_days_cons2 <- function(x){
n <- length(x)
if(n < 2) x
out <- integer(n)
y <- rle(x)
cur_pos <- 1
for(i in seq_len(length(y$lengths))){
out[(cur_pos):(cur_pos y$lengths[i]-1)] <- cumsum(rep(y$values[i], y$lengths[i]))
cur_pos <- cur_pos y$lengths[i]
}
out
}
# this formulation was faster on some tests, and would be easier to rewrite in C
nb_days_cons <- function(x){
n <- length(x)
if(n < 2) x
out <- integer(n)
out[1] <- x[1]
for(i in 2:n){
if(x[i] == x[i-1]){
out[i] <- out[i-1] x[i]
} else{
out[i] <- x[i]
}
}
out
}
Как только у нас есть эта функция, dplyr
часть довольно классическая.
df %>%
group_by(Stocks) %>%
arrange(Date) %>% # make sure of order
mutate(change = c(0, diff(Close_Price)),
stretch_duration = nb_days_cons(sign(change))) %>%
arrange(Stocks)
#> # A tibble: 18 x 5
#> # Groups: Stocks [3]
#> Stocks Date Close_Price change stretch_duration
#> <chr> <chr> <int> <dbl> <dbl>
#> 1 A 11/11/2020 11 0 0
#> 2 A 11/12/2020 19 8 1
#> 3 A 11/13/2020 7 -12 -1
#> 4 A 11/16/2020 17 10 1
#> 5 A 11/17/2020 24 7 2
#> 6 A 11/18/2020 31 7 3
#> 7 B 11/11/2020 50 0 0
#> 8 B 11/12/2020 62 12 1
#> 9 B 11/13/2020 63 1 2
#> 10 B 11/16/2020 70 7 3
#> 11 B 11/17/2020 52 -18 -1
#> 12 B 11/18/2020 61 9 1
#> 13 C 11/11/2020 164 0 0
#> 14 C 11/12/2020 125 -39 -1
#> 15 C 11/13/2020 165 40 1
#> 16 C 11/16/2020 170 5 2
#> 17 C 11/17/2020 165 -5 -1
#> 18 C 11/18/2020 157 -8 -2
Created on 2020-11-19 by the reprex package (v0.3.0)
Конечно, окончательный arrange()
вариант предназначен только для удобства визуализации, и вы можете удалить столбцы, которые вам больше не нужны select()
.
Комментарии:
1. результаты в последнем столбце неверны. Например, акции С датой 17 ноября должны иметь значение -1, а 18 ноября должны иметь значение -2, чтобы показать 2 последовательных отрицательных закрытия. Оно никогда не должно быть равным нулю, потому что положительное отрицательное значение не предполагается вычеркивать.
2. О, я не понял, что вы этого хотели, прямо сейчас это количество последовательных записей с одинаковым знаком, так что вы можете легко извлечь те, у которых 3 или 4 дня подряд. Я редактирую свой ответ, чтобы добавить подписанный столбец (просто путем умножения на
pos
).3. Alexlok, это все еще неверно. после положительного значения 1, если на следующий день акции закрываются с отрицательным значением, результат не должен быть нулевым. При каждом положительном или отрицательном закрытии отсчет должен начинаться с -1 или 1 соответственно. поэтому ответ в последнем столбце никогда не должен быть нулевым. Надеюсь, я смогу прояснить. мой ожидаемый результат для stock C 17 ноября -1, а 18 ноября -2. Пожалуйста, помогите улучшить код.
4. Соответствует ли это ожиданиям сейчас?
5. Да, это соответствует ожиданиям. Как я могу дать оценку 5 звезд и этому веб-сайту за такую блестящую поддержку? Я хотел бы подтвердить только одну вещь, потому что пока я не могу подтвердить результаты. Как этот код будет связан с пробелами в датах, таких как выходные или какие-либо конкретные акции, не торгуемые в какую-либо конкретную дату?