根据列表中数据帧的文件名对大列表中的数据进行子集化

Subset data in a large list based on filename of the dataframes in the list

我正在处理一个包含 450 个数据帧的大型列表。我将举一个 数据帧名称的例子:

ALL_SM51_SE1_hourly, ALL_SM201_SE1_hourly, ALL_SM501_SE1_hourly
ALL_SM51_SE2_hourly, ALL_SM201_SE2_hourly, ALL_SM501_SE2_hourly
...................................................................
ALL_SM51_SE150_hourly, ALL_SM201_SE150_hourly, ALL_SM501_SE150_hourly

数据帧包含不同深度(5cm、20cm、50cm,在文件名中用"SM51, SM201, SM501"表示的土壤水分测量数据,并且有150 个传感器 由文件名中的 "SE1, SE2, SE3, ..." 表示)这就是为什么我有 450 个数据帧存储在列表中的原因。

我想做什么:我想为每个包含 3 个元素的传感器创建一个新列表(创建一个子集)。所以我想要一个 SE1、SE2、SE3、...、SE150 的列表以及相应的测量深度。

我已经为我的问题搜索了合适的答案,但我只找到了按特定值对数据进行子集化的答案,但我想按文件名 进行子集化。

有人知道怎么做吗?

使用正则表达式,您可以识别独特的传感器 un.se,您可以从 pastenew.names。原始列表 lst 然后可以 split 变成唯一的传感器, ordered 并转换成 data.frames.

un.se <- gsub(".*SE(\d+).*", "\1", names(lst))
new.names <- paste0("SE", unique(un.se))
tmp <- setNames(split(lst, un.se), paste0("SE", unique(un.se)))
res <- lapply(tmp, function(x) {
  nm <- gsub(".*SM(\d+).*", "\1", names(x))
  setNames(lapply(x[order(nm)], data.frame), paste0("d", gsub("1$", "", nm)))
  })

解释 gsub-regex:

在正则表达式 .* 中查找任何 "character-until",然后我们从字面上得到 SE。现在我们在括号 ( ) 内使用分组,在这里我们用 \d+ 查找一个或多个数字或 digit。在第二个 gsub 参数中 \1 对第一组(括号中的)进行反向引用以替换整个字符串。例如。结果 un.se 是在每个字符串中的每个 SE 之后找到的数字(参见:https://regex101.com/r/zuO8Ts/1;并注意我们需要在 R 中进行双重转义 \)。

这会在子列表中列出每个传感器以及每个深度的数据帧。

结果

res
# $SE1
# $SE1$d5
#   x1 x2 x3
# 1  1  2  3
# 
# $SE1$d20
#   x1 x2 x3
# 1  1  2  3
# 
# $SE1$d50
#   x1 x2 x3
# 1  1  2  3
# 
# 
# $SE2
# $SE2$d5
#   x1 x2 x3
# 1  1  2  3
# 
# $SE2$d20
#   x1 x2 x3
# 1  1  2  3
# 
# $SE2$d50
#   x1 x2 x3
# 1  1  2  3

玩具资料

lst <- list(ALL_SM51_SE1_hourly = list(x1 = 1, x2 = 2, x3 = 3), ALL_SM201_SE1_hourly = list(
    x1 = 1, x2 = 2, x3 = 3), ALL_SM501_SE1_hourly = list(x1 = 1, 
    x2 = 2, x3 = 3), ALL_SM51_SE2_hourly = list(x1 = 1, x2 = 2, 
    x3 = 3), ALL_SM201_SE2_hourly = list(x1 = 1, x2 = 2, x3 = 3), 
    ALL_SM501_SE2_hourly = list(x1 = 1, x2 = 2, x3 = 3))