如果此问题之前已得到充分回答,请提前道歉。我在这里查了各种 lapply 问题,但还没有找到一个完全像这种情况的。
我有 4 家公司的数据,它们有 8 个不同日期的 .xlsx 文件。为清楚起见,共有 32 个 .xlsx 文件(每个公司日期组合 1 个)。八个日期是路径中的上层文件结构,其中第一个文件夹是“01-01-19”,第二个是“02-01-19”等。在每个文件夹中,四个公司有不同的文件我可以使用 grepl
准确识别它是哪家公司的名称。
我的目标是根据文件名读取特定范围的 .xlsx 文件,然后将特定公司的所有数据表放在一起rbind
或 rbindlist
。>
我目前的方法是使用 lapply 遍历文件名(日期,例如“01-01-19”)。然后有一次,我在具有特定公司 .xlsx 文件的较低级别文件夹结构中,我可以再次使用嵌套的 lapply 循环读取每个表作为 data.table。我使用 if-else 语句来检查公司名称,因为每家公司都有不同数量的观察值,这些观察值在所有时间段内都是一致的(即 co1 在每个时期将始终有 100 个观察值,但 co2 每个时期可能有 300 个观察值,等等。 )
我目前的方法如下:
# get the files which are indexed by date - e.g. "01-01-2019"
files <- list.files(path=file.path(input_fld,"co_data"))
# nested lapplys to 1. loop through the outer files (dates) and 2. loop through the inner four files (companies) conditionally
co_dt_list <- lapply(files, function(x) {
# get the files inside the index_data
in_files <- list.files(path=file.path(input_fld,"co_data",x))
# the second lapply to loop through each of the company names individually
lapply(in_files, function(y) {
if (grepl("co1", y) == TRUE) {
# if the file name has "co1" in the name, read this as a data.table
data.table(read_excel(file.path(input_fld, "co_data", x, y), range = "A15:Q115"))
} else if (grepl("co2", y) == TRUE) {
# if the file name has "co2" in the name, read this as a data.table
data.table(read_excel(file.path(input_fld, "co_data", x, y), range = "A15:Q315"))
} else if (grepl("co3", y) == TRUE) {
# if the file name has "co3" in the name, read this as a data.table
data.table(read_excel(file.path(input_fld, "co_data", x, y), range = "A15:Q515"))
} else {
# else read in this as a data.table
data.table(read_excel(file.path(input_fld, "co_data", x, y), range = "A15:Q715"))
}
})
})
这个循环在功能上按所写的方式工作,但让我得到了不想要的输出。它将每个日期索引为第一个列表索引,将公司索引为第二个(内部)列表索引。换句话说,data.tables 的第一个列表将是 01-01-19 的 co1、co2、co3 和 co4,而第二个列表将与 02-01-19 等相同。
我为下面的输出创建了一些合成数据。请原谅提前组合列表的手动工作。
# generate a date list
date_list <- seq.Date(as.Date("2019-01-01"), as.Date("2019-08-01"), by = "month")
# generate fake datasets by date
co1 <- lapply(date_list, function(x) { data.table(co = 1, date = x, data = rnorm(100)) })
co2 <- lapply(date_list, function(x) { data.table(co = 2, date = x, data = rnorm(300)) })
co3 <- lapply(date_list, function(x) { data.table(co = 3, date = x, data = rnorm(500)) })
co4 <- lapply(date_list, function(x) { data.table(co = 4, date = x, data = rnorm(700)) })
# put them together in current list format
list_1 <- list(co1[[1]], co2[[1]], co3[[1]], co4[[1]])
list_2 <- list(co1[[2]], co2[[2]], co3[[2]], co4[[2]])
list_3 <- list(co1[[3]], co2[[3]], co3[[3]], co4[[3]])
list_4 <- list(co1[[4]], co2[[4]], co3[[4]], co4[[4]])
list_5 <- list(co1[[5]], co2[[5]], co3[[5]], co4[[5]])
list_6 <- list(co1[[6]], co2[[6]], co3[[6]], co4[[6]])
list_7 <- list(co1[[7]], co2[[7]], co3[[7]], co4[[7]])
list_8 <- list(co1[[8]], co2[[8]], co3[[8]], co4[[8]])
# this is what the output looks like
list_output <- list(list_1, list_2, list_3, list_4,
list_5, list_6, list_7, list_8)
我的问题是:有没有一种简单的方法可以 a) 将我当前形式的 list_output 和 rbind
或 rbindlist
每家公司的 data.tables 相互转换?或者,b) 是否有更好的方法来构建初始嵌套的 lapply 循环以获得由公司而不是日期索引的输出?
谢谢!
答案 0 :(得分:1)
这是一个仅使用 data.table 的解决方案。如果您的列表元素为 id 列正确命名会有所帮助:
rbindlist(lapply(list_output, rbindlist, idcol = "list_inner"), idcol = "list_outer")
这提供了一个整洁的表格,您可以根据需要进行过滤:
list_outer list_inner co date data
1: 1 1 1 2019-01-01 1.3593594
2: 1 1 1 2019-01-01 1.1514190
3: 1 1 1 2019-01-01 -0.5982100
4: 1 1 1 2019-01-01 0.2675609
5: 1 1 1 2019-01-01 -0.7936896
---
12796: 8 4 4 2019-08-01 2.3255672
12797: 8 4 4 2019-08-01 -1.6454320
12798: 8 4 4 2019-08-01 0.2871383
12799: 8 4 4 2019-08-01 0.7126838
12800: 8 4 4 2019-08-01 -1.3650915