首页 > 解决方案 > 如何遍历列表列表,同时基于变量对列表进行子集化

问题描述

我有一个类似于此处给出的玩具示例的列表列表。我想遍历该列表以返回一个新列表,该列表已根据变量删除了元素。


输入(头(列表)):

list(FEB_gems = list(GAME1 = structure(list(GAME1_Class = structure(c(2L, 
1L, 5L, 4L, 3L), .Label = c("fighter", "paladin", "rouge", "sorcerer", 
"wizard"), class = "factor"), GAME1_Race = structure(c(3L, 1L, 
4L, 3L, 2L), .Label = c("elf", "gnome", "human", "orc"), class = "factor"), 
GAME1_Alignment = structure(c(4L, 2L, 1L, 5L, 3L), .Label = c("CE", 
"CG", "LG", "NE", "NN"), class = "factor"), GAME1_Level = c(6, 
7, 6, 7, 7), GAME1_Alive = structure(c(1L, 1L, 1L, 1L, 1L
), .Label = "y", class = "factor")), class = "data.frame", row.names = c(NA, 
-5L)), GAME2 = structure(list(GAME2_Class = structure(c(3L, 5L, 
2L, 4L, 1L), .Label = c("bard", "cleric", "fighter", "monk", 
"wizard"), class = "factor"), GAME2_Race = structure(c(2L, 3L, 
2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"), class = "factor"), 
GAME2_Alignment = structure(c(4L, 2L, 1L, 5L, 3L), .Label = c("CE", 
"CG", "LG", "NE", "NN"), class = "factor"), GAME2_Level = c(5, 
5, 5, 5, 5), GAME2_Alive = structure(c(1L, 2L, 2L, 2L, 2L
), .Label = c("n", "y"), class = "factor")), class = "data.frame", row.names = c(NA, 
-5L))), MAR_gems = list(GAME3 = structure(list(GAME3_Class = structure(c(2L, 
1L, 5L, 4L, 3L), .Label = c("barbarian", "cleric", "monk", "ranger", 
"warlock"), class = "factor"), GAME3_Race = structure(c(2L, 3L, 
2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"), class = "factor"), 
GAME3_Alignment = structure(c(2L, 2L, 1L, 3L, 2L), .Label = c("CE", 
"LG", "LN"), class = "factor"), GAME3_Level = c(1, 1, 1, 
1, 1), GAME3_Alive = structure(c(2L, 2L, 2L, 1L, 2L), .Label = c("n", 
"y"), class = "factor")), class = "data.frame", row.names = c(NA, 
-5L)), GAME4 = structure(list(GAME4_Class = structure(c(2L, 1L, 
5L, 4L, 3L), .Label = c("fighter", "paladin", "rouge", "sorcerer", 
"wizard"), class = "factor"), GAME4_Race = structure(c(2L, 3L, 
 2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"), class = "factor"), 
GAME4_Alignment = structure(c(1L, 2L, 1L, 4L, 3L), .Label = c("CE", 
"CG", "LG", "LN"), class = "factor"), GAME4_Level = c(5, 
5, 5, 5, 5), GAME4_Alive = structure(c(1L, 2L, 2L, 2L, 2L
), .Label = c("n", "y"), class = "factor")), class = "data.frame", row.names = c(NA, 
-5L))))

我已经尝试手动设置列表列表。一个函数会更好,因为我有多种类型的数据要子集。

1)基于整数子设置级别列

df1 <- Games.Split[[1]][[1]]
Level <- df1[which(df1[4] > 6),]
Games.Split[[1]][[1]] <- Level

df1:

  GAME1_Class GAME1_Race GAME1_Alignment GAME1_Level GAME1_Alive
1     paladin      human              NE           6           y
2     fighter        elf              CG           7           y
3      wizard        orc              CE           6           y
4    sorcerer      human              NN           7           y
5       rouge      gnome              LG           7           y

等级:

 GAME1_Class GAME1_Race GAME1_Alignment GAME1_Level GAME1_Alive
2     fighter        elf              CG           7           y
4    sorcerer      human              NN           7           y
5       rouge      gnome              LG           7           y

2)基于字符串子设置Alive列

df2 <- Games.Split[[1]][[2]]
Alive <- df2[which(df2[5] == 'y'),]
Games.Split[[1]][[2]] <- Alive

df2:

 GAME2_Class GAME2_Race GAME2_Alignment GAME2_Level GAME2_Alive
1     fighter        elf              NE           5           n
2      wizard   half-elf              CG           5           y
3      cleric        elf              CE           5           y
4        monk      human              NN           5           y
5        bard      dwarf              LG           5           y

活:

 GAME2_Class GAME2_Race GAME2_Alignment GAME2_Level GAME2_Alive
2      wizard   half-elf              CG           5           y
3      cleric        elf              CE           5           y
4        monk      human              NN           5           y
5        bard      dwarf              LG           5           y

但是,我正在努力在 for 循环中将其付诸实施,以在整个列表中执行这些子设置任务。

for (i in Games.Split){
  for (j in i){
    Alive = j[which(j[5] == 'y'),]
    j <- Alive
  }
}

总的来说,一个函数/方法可以遍历整个列表以提供一个不再包含已删除元素的新列表。

标签: rlistfor-loop

解决方案


由于您有两个级别的列表来组织数据帧,因此这将需要一个嵌套列表应用函数 ( lapply) - 与循环相同,但更简洁一些。下面是一个示例,它创建了一个基于最大级别 (maxLevel) 对游戏列表 (gameList) 进行子集化的函数:

listSubset <- function(x, maxLevel){
  lapply(x, function(ls){
    lapply(ls, function(df) df[df[[grep('Level', names(df), value = TRUE)]] < maxLevel, ])
  })
}
listSubset(x = gameList, maxLevel = 6)

输出:

$`FEB_gems`
$`FEB_gems`$`GAME1`
[1] GAME1_Class     GAME1_Race      GAME1_Alignment GAME1_Level     GAME1_Alive    
<0 rows> (or 0-length row.names)

$`FEB_gems`$GAME2
  GAME2_Class GAME2_Race GAME2_Alignment GAME2_Level GAME2_Alive
1     fighter        elf              NE           5           n
2      wizard   half-elf              CG           5           y
3      cleric        elf              CE           5           y
4        monk      human              NN           5           y
5        bard      dwarf              LG           5           y


$MAR_gems
$MAR_gems$`GAME3`
  GAME3_Class GAME3_Race GAME3_Alignment GAME3_Level GAME3_Alive
1      cleric        elf              LG           1           y
2   barbarian   half-elf              LG           1           y
3     warlock        elf              CE           1           y
4      ranger      human              LN           1           n
5        monk      dwarf              LG           1           y

$MAR_gems$GAME4
  GAME4_Class GAME4_Race GAME4_Alignment GAME4_Level GAME4_Alive
1     paladin        elf              CE           5           n
2     fighter   half-elf              CG           5           y
3      wizard        elf              CE           5           y
4    sorcerer      human              LN           5           y
5       rouge      dwarf              LG           5           y

所有功能都在 base R 中,因此无需安装和学习新包。


推荐阅读