我有一个关于从R中的data.frame中提取多个值并将它们放入新的data.frame中的问题。
我有一个看起来像这样的数据框(df)
PRICE EVENT
1.50 0
1.70 0
1.65 0
1.20 1
0.90 0
1.70 0
1.55 0
. .
. .
1.10 0
1.20 0
1.14 1
0.90 0
我的实际data.frame有这两列和超过300.000行。名为EVENT的列仅具有值0 OR 1(值1是发生特定事件的代理)。
我的研究的第一步:如果事件发生,分析价格。 第一步很简单。我用
做到了vector<-df[df$EVENT==1, "PRICE"]
现在vector
包含活动日的所有价格。 (这里:1.20和1.14)
但是现在我研究的第二步是它变得有趣:
现在我不仅要求参加活动日的价格,还需要活动日前后x天的价格,并将它们放入矩阵
例如:我想要在活动前两天和活动后一天(包括活动日)的价格
比我想要创建的新data.frame看起来像
Event 1 Event n
-2 1.70 ... 1.10
-1 1.65 ... 1.20
0 1.20 ... 1.14
+1 0.90 ... 0.90
请记住,4天跨度[-2:1]只是一个例子。在我的实际研究中,我必须涵盖91天的跨度[-30:60]。
感谢您的帮助:)
答案 0 :(得分:4)
我们可以创建一个包含相关行号的矩阵,然后将其用作掩码来达到预期的输出:
event_rows <- which(df$EVENT==1)
mask <- sapply(event_rows, function(x) (x-2):(x+2))
apply(mask, 2, function(x) df$PRICE[x])
# [,1] [,2]
#[1,] 1.70 1.10
#[2,] 1.65 1.20
#[3,] 1.20 1.14
#[4,] 0.90 0.90
#[5,] 1.70 NA
数据强>
df <- structure(list(PRICE = c(1.5, 1.7, 1.65, 1.2, 0.9, 1.7, 1.55,
1.1, 1.2, 1.14, 0.9), EVENT = c(0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L,
0L, 1L, 0L)), .Names = c("PRICE", "EVENT"), class = "data.frame", row.names = c(NA,
-11L))
答案 1 :(得分:2)
为了完成,这里有一个基础R
解决方案:
# example data
set.seed(123)
df <- data.frame(price = rnorm(100), event = rbinom(100, 1, 0.05))
# create a vector of unique event positions with additional 2 positions before and 1 ahead
offset <- unique(as.vector(sapply(which(df$event == 1), function(x) c((x-2):(x+1)))))
# subset data
df[offset[offset >0 & offset <= 100],]
price event
1 -0.56047565 0
2 -0.23017749 1
3 1.55870831 0
20 -0.47279141 0
21 -1.06782371 0
22 -0.21797491 1
23 -1.02600445 0
46 -1.12310858 0
47 -0.40288484 0
48 -0.46665535 1
49 0.77996512 1
50 -0.08336907 0
62 -0.50232345 0
63 -0.33320738 0
64 -1.01857538 1
65 -1.07179123 0
75 -0.68800862 0
76 1.02557137 0
77 -0.28477301 1
78 -1.22071771 0
95 1.36065245 0
96 -0.60025959 0
97 2.18733299 1
98 1.53261063 0
编辑:我最初没有看到预期的输出,请参阅@ mtoto的答案。
答案 2 :(得分:0)
我要做的是,用滞后扩展基础数据数据框,然后按行选择。使用tidyverse就可以这样了。 (我强烈建议使用tidyverse而不是基础R.但这取决于你)
library(tidyverse)
# generate example data frame
df <- data.frame(price = rnorm(100), event = rbinom(100, 1, 0.5))
# generate a vector from one the desired number of lags.
# we map this vector with a function that returns the lagged
# values of the price. then we join by columns
lags <- map(1:3, function(x){lag(df$price, n = x)}) %>%
reduce(cbind) %>% as.data.frame %>%
set_names(paste('priceLag', 1:3, sep = ''))
# bind lags to original data frame, select events == 1
out <- cbind(df, lags) %>% filter(df$event == 1)
答案 3 :(得分:0)
library('tidyverse')
df <- data.frame(
price = seq_len(20),
event = c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0))
df
# price event
# 1 1 0
# 2 2 0
# 3 3 0
# 4 4 0
# 5 5 1
# 6 6 0
# 7 7 0
# 8 8 0
# 9 9 0
# 10 10 0
# 11 11 0
# 12 12 1
# 13 13 0
# 14 14 0
# 15 15 0
# 16 16 1
# 17 17 1
# 18 18 0
# 19 19 0
# 20 20 0
您可以使用lag
和lead
来获取偏移值。然后使用gather
和spread
的组合将数据框翻转为所需的形状。
df %>%
mutate(
`-2` = lag(price, 2),
`-1` = lag(price),
`0` = price,
`+1` = lead(price)) %>%
select(-price) %>%
filter(event == 1) %>%
mutate(event = paste0('event_', seq_along(event))) %>%
gather('offset', 'value', -event) %>%
spread(event, value) %>%
arrange(as.numeric(offset))
# offset event_1 event_2 event_3 event_4
# 1 -2 3 10 14 15
# 2 -1 4 11 15 16
# 3 0 5 12 16 17
# 4 +1 6 13 17 18