[英]Filtering using a list of value in R with lapply() is too slow
我有一個獨特的股票名稱列表(大約 12,000 只股票)及其“以前的最大收入”和相當大的 dataframe。 dataframe 有股票名稱、收入、收入年份。 例如:
AAPL | 2000 | 1,000
AAPL | 2001 | 1,200
AAPL | 2002 | 900
AMZN | 2000 | 300
AMZN | 2001 | 500
MSFT | 2000 | 600
我需要檢查哪一年股票超過了大型 dataframe 的“以前的最大收入”。 由於每家公司報告的收入年份不同,有的有 2000-2002 年的數據,有的有更多(2000-2005 年),有的有更少(2000-2001 年)。
我的方法是篩選股票名稱。 所以,我必須對每只股票都這樣做。 這就是為什么我使用 lapply() 但它太慢了。
下面是我要說的部分。
rec_year <- function(sym) {
recovery_year <- (post_table %>% filter(tic==sym & ni > pre_max_table[pre_max_table$tic==sym]$ni))$fyear[1]
return(recovery_year - pre_max_table[pre_max_table$tic==sym]$fyear)
}
YearsRecover <- unlist(lapply(tic_list,rec_year))
ni:凈收入 tic:股票名稱 fyear:財政年度
pre_max_table
包含股票列表以及它們之前的最大收入。 例如:蘋果 | 2001 | 1,200 亞馬遜 | 2002 | 900 毫秒 | 2001 | 1000
post_table
包含新數據以檢查pre_max_table
中的先前最大值
function rec_year()
首先檢查pre_max_table
中之前的最大凈收入。 然后它檢查股票名稱sym
在哪一年超過了之前的最大值。 如果它找到了一年,它會返回上一個最大收入的年份與sym
打破自己記錄的年份之間的差值。 然后我使用lapply()
將此rec_year()
應用於tic_list
中的股票列表
我認為代碼運行緩慢,因為它必須遍歷許多 tic 名稱(12k)。 每次它必須重新運行rec_year()
function。
如果有人能提出更好/更快的方法來解決這個問題,我將不勝感激。
由於pre_max_table
似乎是data.table
,所以第一步我會setkey(pre_max_table, tic)
,這樣
recovery_year <- (post_table %>% filter(tic==sym & ni > pre_max_table[pre_max_table$tic==sym]$ni))$fyear[1]
可以修改為
recovery_year <- (post_table %>% filter(tic==sym & ni > pre_max_table[sym]$ni))$fyear[1]
然后我觀察到使用filter()
會減慢代碼的速度,所以我進一步修改為
recovery_year <- post_table[post_table$tic==sym & post_table$ni > pre_max_table[sym]$ni, "fyear"][1]
有沒有辦法在不使用 lapply() 的情況下做到這一點(為每個組找到一個特定的值)?
這是一種與原始方法相反的方法,首先選擇所有收入較高的行,然后從這些行中刪除除每只股票的第一行之外的所有行:
# pick all rows from post_table with income higher than that from pre_max_table
ps = subset(post_table, ni > pre_max_table[post_table['tic']]$ni)
# pick only the first row for each stock
pnd = ps[!duplicated(ps$tic), c('tic', 'fyear')]
# compute the "recover" time for each stock (including NAs)
YearsRecover = pnd[levels(pnd$tic), 'fyear'] - pre_max_table$fyear
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.