R - 根据另一列中的指标从数据框中提取多行
R - Extracting more than one row from a data frame based on an indicator in another column
我有一个关于根据指标
从 R 中的 data.frame 中提取多个值的问题
我有一个 data.frame 看起来像这样 (df)
ROW COMPANY PRICE DATE EVENT
1 APPLE 1.50 Jan02 0
2 APPLE 1.70 Feb02 1
3 APPLE 1.65 Mar02 0
4 APPLE 1.20 Apr02 0
5 APPLE 1.30 May02 0
6 APPLE 1.14 Jun02 0
7 APPLE 1.10 Jul02 0
. . . . .
. . . . .
349.997 MICROSOFT 0.80 Sep16 0
349.998 MICROSOFT 0.65 Oct16 0
349.999 MICROSOFT 1.10 Nov16 1
350.000 MICROSOFT 0.90 Dez16 0
如您所见,我有一个很大的 data.frame,其中包含各种公司及其在给定日期的股价。另外我有一个事件列(只有 0 和 1 作为值)。值 1 表示在给定日期发生了特定事件(例如股东大会)。在 350.000 行中,我有 2.500 个事件(这意味着列事件有 2.500 个 1 和 347.500 个零)。
现在我的目标是围绕特定事件分析股价(例如分析事件发生前 10 个月和事件发生后 15 个月的股价)。现在我是如何进行的以及我目前被困在哪里。
首先,我必须根据我的公司拆分我的 data.frame,因为如果我在观察期(2002-2016 年)之外,我需要获得 NA。例如如果苹果在 11 月 16 日有活动,我需要在 2 个月后得到价格,我应该得到一个 NA(因为它在我的观察期之外),但在未分割的 data.frame 中我会得到价格Jan02 的下一家公司。
list<-split(df, f=df$COMPANY)
现在是我卡住的部分。我需要提取每个公司活动日之前的 10 个价格和活动日之后的 15 个价格
我尝试创建的输出看起来像(注意:“?”=这些值存在但它们未显示在上面的示例 df 中)
Event 1 (Apple) Event 2500 (Microsoft)
-10 NA ... ?
-9 NA ... ?
. .
0 1.70 ... 1.10
. .
+15 ? ... NA
抱歉,如果不深入细节就很难正确解释我的问题,但我希望我能在一定程度上说清楚。
感谢您的帮助:)
这可以通过 dplyr
和 tidyr
包来完成,尽管它有点复杂。这是一个小得多的数据集的要点:
library(dplyr)
library(tidyr)
df <- readr::read_csv("COMPANY,PRICE,DATE,EVENT
APPLE,1.50,2002/01/01,0
APPLE,1.70,2002/02/01,1
APPLE,1.65,2002/03/01,0
APPLE,1.20,2002/04/01,0
MICROSOFT,2.50,2002/01/01,0
MICROSOFT,2.70,2002/02/01,0
MICROSOFT,2.65,2002/02/01,1
MICROSOFT,2.20,2002/03/01,0")
df
# A tibble: 8 x 4
COMPANY PRICE DATE EVENT
<chr> <dbl> <date> <int>
1 APPLE 1.50 2002-01-01 0
2 APPLE 1.70 2002-02-01 1
3 APPLE 1.65 2002-03-01 0
4 APPLE 1.20 2002-04-01 0
5 MICROSOFT 2.50 2002-01-01 0
6 MICROSOFT 2.70 2002-02-01 0
7 MICROSOFT 2.65 2002-02-01 1
8 MICROSOFT 2.20 2002-03-01 0
首先,我们需要构建一些滞后和超前。如果您想要更多 pre/post 个活动日,则必须在此处添加更多列。
with_lags <- df %>%
group_by(COMPANY) %>%
mutate(
lag_01 = lag(PRICE, n = 1, order_by = DATE)
, lag_02 = lag(PRICE, n = 2, order_by = DATE)
, lag_00 = lag(PRICE, n = 0, order_by = DATE)
, lead_01 = lead(PRICE, n = 1, order_by = DATE)
, lead_02 = lead(PRICE, n = 2, order_by = DATE)
)
with_lags
# A tibble: 8 x 9
# Groups: COMPANY [2]
COMPANY PRICE DATE EVENT lag_01 lag_02 lag_00 lead_01 lead_02
<chr> <dbl> <date> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
1 APPLE 1.50 2002-01-01 0 NA NA 1.50 1.70 1.65
2 APPLE 1.70 2002-02-01 1 1.50 NA 1.70 1.65 1.20
3 APPLE 1.65 2002-03-01 0 1.70 1.5 1.65 1.20 NA
4 APPLE 1.20 2002-04-01 0 1.65 1.7 1.20 NA NA
5 MICROSOFT 2.50 2002-01-01 0 NA NA 2.50 2.70 2.65
6 MICROSOFT 2.70 2002-02-01 0 2.50 NA 2.70 2.65 2.20
7 MICROSOFT 2.65 2002-02-01 1 2.70 2.5 2.65 2.20 NA
8 MICROSOFT 2.20 2002-03-01 0 2.65 2.7 2.20 NA NA
现在我们只保留 EVENT 为 1 的行,并将数据重新排列回长格式。请注意,您必须编辑调用 gather()
函数的行以反映您在上面构建的 lag/lead 列的列表:
long_form <- with_lags %>%
filter(EVENT == 1) %>%
select(-PRICE, -EVENT, -DATE) %>%
gather(period, price, lag_01:lead_02) %>%
separate(period, c("lag_or_lead", "lag_order")) %>%
mutate(
lag_order = ifelse(lag_or_lead == "lag",
-1 * as.numeric(lag_order),
as.numeric(lag_order))
) %>%
select(-lag_or_lead) %>%
arrange(COMPANY, lag_order)
long_form
# A tibble: 10 x 3
# Groups: COMPANY [2]
COMPANY lag_order price
<chr> <dbl> <dbl>
1 APPLE -2 NA
2 APPLE -1 1.50
3 APPLE 0 1.70
4 APPLE 1 1.65
5 APPLE 2 1.20
6 MICROSOFT -2 2.50
7 MICROSOFT -1 2.70
8 MICROSOFT 0 2.65
9 MICROSOFT 1 2.20
10 MICROSOFT 2 NA
如果您需要宽格式,则可以使用 tidyr
包中的 spread()
将公司移至列中。
我可能会因为建议(震惊恐怖)在 base R 中执行此操作而被拒绝,但是恕我直言,易于理解和编辑的代码通常比更简洁但更难理解的编程更可取。只有 2500 个事件,我认为它应该足够快了。如果您可以将解决方案的速度与您的真实数据进行比较,那将会很有趣吗?
set.seed(0)
SP <- data.frame(Company = c(rep_len("Apple", 50),
rep_len("Microsoft", 50)),
Price = round(runif(100, 1, 2), 2),
Date = rep(seq.Date(from = as.Date("2002-01-01"),
length.out = 50, by = "month"),
2),
Event = rbinom(100, 1, 0.05),
stringsAsFactors = FALSE)
Event <- which(SP$Event %in% 1)
resultFrame <- data.frame(Period = (-10):15)
for (i in Event){
Stock <- SP$Company[i]
eventTime <- format(SP$Date[i], "%b-%Y")
stockWin <- (i - 10):(i + 15)
stockWin[stockWin <= 0 | stockWin > nrow(SP)] <- NA
stockWin[!(SP$Company[stockWin] %in% Stock)] <- NA
priceWin <- SP[stockWin, "Price"]
eventName <- paste("Event", eventTime, Stock, sep=".")
resultFrame <- data.frame(resultFrame, priceWin)
names(resultFrame)[ncol(resultFrame)] <- eventName
}
我有一个关于根据指标
从 R 中的 data.frame 中提取多个值的问题我有一个 data.frame 看起来像这样 (df)
ROW COMPANY PRICE DATE EVENT
1 APPLE 1.50 Jan02 0
2 APPLE 1.70 Feb02 1
3 APPLE 1.65 Mar02 0
4 APPLE 1.20 Apr02 0
5 APPLE 1.30 May02 0
6 APPLE 1.14 Jun02 0
7 APPLE 1.10 Jul02 0
. . . . .
. . . . .
349.997 MICROSOFT 0.80 Sep16 0
349.998 MICROSOFT 0.65 Oct16 0
349.999 MICROSOFT 1.10 Nov16 1
350.000 MICROSOFT 0.90 Dez16 0
如您所见,我有一个很大的 data.frame,其中包含各种公司及其在给定日期的股价。另外我有一个事件列(只有 0 和 1 作为值)。值 1 表示在给定日期发生了特定事件(例如股东大会)。在 350.000 行中,我有 2.500 个事件(这意味着列事件有 2.500 个 1 和 347.500 个零)。
现在我的目标是围绕特定事件分析股价(例如分析事件发生前 10 个月和事件发生后 15 个月的股价)。现在我是如何进行的以及我目前被困在哪里。
首先,我必须根据我的公司拆分我的 data.frame,因为如果我在观察期(2002-2016 年)之外,我需要获得 NA。例如如果苹果在 11 月 16 日有活动,我需要在 2 个月后得到价格,我应该得到一个 NA(因为它在我的观察期之外),但在未分割的 data.frame 中我会得到价格Jan02 的下一家公司。
list<-split(df, f=df$COMPANY)
现在是我卡住的部分。我需要提取每个公司活动日之前的 10 个价格和活动日之后的 15 个价格
我尝试创建的输出看起来像(注意:“?”=这些值存在但它们未显示在上面的示例 df 中)
Event 1 (Apple) Event 2500 (Microsoft)
-10 NA ... ?
-9 NA ... ?
. .
0 1.70 ... 1.10
. .
+15 ? ... NA
抱歉,如果不深入细节就很难正确解释我的问题,但我希望我能在一定程度上说清楚。
感谢您的帮助:)
这可以通过 dplyr
和 tidyr
包来完成,尽管它有点复杂。这是一个小得多的数据集的要点:
library(dplyr)
library(tidyr)
df <- readr::read_csv("COMPANY,PRICE,DATE,EVENT
APPLE,1.50,2002/01/01,0
APPLE,1.70,2002/02/01,1
APPLE,1.65,2002/03/01,0
APPLE,1.20,2002/04/01,0
MICROSOFT,2.50,2002/01/01,0
MICROSOFT,2.70,2002/02/01,0
MICROSOFT,2.65,2002/02/01,1
MICROSOFT,2.20,2002/03/01,0")
df
# A tibble: 8 x 4
COMPANY PRICE DATE EVENT
<chr> <dbl> <date> <int>
1 APPLE 1.50 2002-01-01 0
2 APPLE 1.70 2002-02-01 1
3 APPLE 1.65 2002-03-01 0
4 APPLE 1.20 2002-04-01 0
5 MICROSOFT 2.50 2002-01-01 0
6 MICROSOFT 2.70 2002-02-01 0
7 MICROSOFT 2.65 2002-02-01 1
8 MICROSOFT 2.20 2002-03-01 0
首先,我们需要构建一些滞后和超前。如果您想要更多 pre/post 个活动日,则必须在此处添加更多列。
with_lags <- df %>%
group_by(COMPANY) %>%
mutate(
lag_01 = lag(PRICE, n = 1, order_by = DATE)
, lag_02 = lag(PRICE, n = 2, order_by = DATE)
, lag_00 = lag(PRICE, n = 0, order_by = DATE)
, lead_01 = lead(PRICE, n = 1, order_by = DATE)
, lead_02 = lead(PRICE, n = 2, order_by = DATE)
)
with_lags
# A tibble: 8 x 9
# Groups: COMPANY [2]
COMPANY PRICE DATE EVENT lag_01 lag_02 lag_00 lead_01 lead_02
<chr> <dbl> <date> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
1 APPLE 1.50 2002-01-01 0 NA NA 1.50 1.70 1.65
2 APPLE 1.70 2002-02-01 1 1.50 NA 1.70 1.65 1.20
3 APPLE 1.65 2002-03-01 0 1.70 1.5 1.65 1.20 NA
4 APPLE 1.20 2002-04-01 0 1.65 1.7 1.20 NA NA
5 MICROSOFT 2.50 2002-01-01 0 NA NA 2.50 2.70 2.65
6 MICROSOFT 2.70 2002-02-01 0 2.50 NA 2.70 2.65 2.20
7 MICROSOFT 2.65 2002-02-01 1 2.70 2.5 2.65 2.20 NA
8 MICROSOFT 2.20 2002-03-01 0 2.65 2.7 2.20 NA NA
现在我们只保留 EVENT 为 1 的行,并将数据重新排列回长格式。请注意,您必须编辑调用 gather()
函数的行以反映您在上面构建的 lag/lead 列的列表:
long_form <- with_lags %>%
filter(EVENT == 1) %>%
select(-PRICE, -EVENT, -DATE) %>%
gather(period, price, lag_01:lead_02) %>%
separate(period, c("lag_or_lead", "lag_order")) %>%
mutate(
lag_order = ifelse(lag_or_lead == "lag",
-1 * as.numeric(lag_order),
as.numeric(lag_order))
) %>%
select(-lag_or_lead) %>%
arrange(COMPANY, lag_order)
long_form
# A tibble: 10 x 3
# Groups: COMPANY [2]
COMPANY lag_order price
<chr> <dbl> <dbl>
1 APPLE -2 NA
2 APPLE -1 1.50
3 APPLE 0 1.70
4 APPLE 1 1.65
5 APPLE 2 1.20
6 MICROSOFT -2 2.50
7 MICROSOFT -1 2.70
8 MICROSOFT 0 2.65
9 MICROSOFT 1 2.20
10 MICROSOFT 2 NA
如果您需要宽格式,则可以使用 tidyr
包中的 spread()
将公司移至列中。
我可能会因为建议(震惊恐怖)在 base R 中执行此操作而被拒绝,但是恕我直言,易于理解和编辑的代码通常比更简洁但更难理解的编程更可取。只有 2500 个事件,我认为它应该足够快了。如果您可以将解决方案的速度与您的真实数据进行比较,那将会很有趣吗?
set.seed(0)
SP <- data.frame(Company = c(rep_len("Apple", 50),
rep_len("Microsoft", 50)),
Price = round(runif(100, 1, 2), 2),
Date = rep(seq.Date(from = as.Date("2002-01-01"),
length.out = 50, by = "month"),
2),
Event = rbinom(100, 1, 0.05),
stringsAsFactors = FALSE)
Event <- which(SP$Event %in% 1)
resultFrame <- data.frame(Period = (-10):15)
for (i in Event){
Stock <- SP$Company[i]
eventTime <- format(SP$Date[i], "%b-%Y")
stockWin <- (i - 10):(i + 15)
stockWin[stockWin <= 0 | stockWin > nrow(SP)] <- NA
stockWin[!(SP$Company[stockWin] %in% Stock)] <- NA
priceWin <- SP[stockWin, "Price"]
eventName <- paste("Event", eventTime, Stock, sep=".")
resultFrame <- data.frame(resultFrame, priceWin)
names(resultFrame)[ncol(resultFrame)] <- eventName
}