【问题标题】:How to extract the rownames of all lists in a list of lists and store these in either a new dataframe or list of lists如何提取列表列表中所有列表的行名并将它们存储在新数据框或列表列表中
【发布时间】:2023-03-05 05:51:01
【问题描述】:

我有一个列表列表。下面给出了一个类似的玩具示例。我想从每个列表中提取行名,然后将这些行名存储在一个新的数据框或一个新的列表列表中(与原始列表的结构相同)。

理想情况下,列名或新列表名称应与列表列表中的列表名称相同。

注意。这些列表的长度都不同,必须加以考虑。我宁愿不要用 N/A 填充空白。


dput(head(Chars_alive)):

list(FEB_games = 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")), row.names = c("Stan", 
"Kenny", "Cartman", "Kyle", "Butters"), class = "data.frame"), 
GAME2 = structure(list(GAME2_Class = structure(c(5L, 2L, 
4L, 1L), .Label = c("bard", "cleric", "fighter", "monk", 
"wizard"), class = "factor"), GAME2_Race = structure(c(3L, 
2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"
), class = "factor"), GAME2_Alignment = structure(c(2L, 1L, 
5L, 3L), .Label = c("CE", "CG", "LG", "NE", "NN"), class = "factor"), 
    GAME2_Level = c(5, 5, 5, 5), GAME2_Alive = structure(c(2L, 
    2L, 2L, 2L), .Label = c("n", "y"), class = "factor")), row.names = c("Kenny", 
"Cartman", "Kyle", "Butters"), class = "data.frame")), MAR_games = list(
GAME3 = structure(list(GAME3_Class = structure(c(2L, 1L, 
5L, 3L), .Label = c("barbarian", "cleric", "monk", "ranger", 
"warlock"), class = "factor"), GAME3_Race = structure(c(2L, 
3L, 2L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"
), class = "factor"), GAME3_Alignment = structure(c(2L, 2L, 
1L, 2L), .Label = c("CE", "LG", "LN"), class = "factor"), 
    GAME3_Level = c(1, 1, 1, 1), GAME3_Alive = structure(c(2L, 
    2L, 2L, 2L), .Label = c("n", "y"), class = "factor")), row.names = c("Stan", 
"Kenny", "Cartman", "Butters"), class = "data.frame"), GAME4 = structure(list(
    GAME4_Class = structure(c(1L, 5L, 4L, 3L), .Label = c("fighter", 
    "paladin", "rouge", "sorcerer", "wizard"), class = "factor"), 
    GAME4_Race = structure(c(3L, 2L, 4L, 1L), .Label = c("dwarf", 
    "elf", "half-elf", "human"), class = "factor"), GAME4_Alignment = structure(c(2L, 
    1L, 4L, 3L), .Label = c("CE", "CG", "LG", "LN"), class = "factor"), 
    GAME4_Level = c(5, 5, 5, 5), GAME4_Alive = structure(c(2L, 
    2L, 2L, 2L), .Label = c("n", "y"), class = "factor")), row.names = c("Kenny", 
"Cartman", "Kyle", "Butters"), class = "data.frame")))

as.data.frame(rownames(Chars_alive[[1]][[1]])) -> GAME1
as.data.frame(rownames(Chars_alive[[2]][[1]])) -> GAME2

由于 GAME1 和 GAME2 的长度不同,因此数据框可能并不理想(我的实际数据在列表列表之间的长度差异很大)。

for (i in Chars_alive) {
  for (j in i)
    rownames(j) -> x
}

for 循环可以工作,但我是循环新手,不知道如何将所有第 j 个元素放入一个新的数据框或列表中。

ls2 <- list(Game1 <- rownames(Chars_alive[[1]][[1]]), Game2 <- rownames(Chars_alive[[1]][[2]]),
                 Game3 <- rownames(Chars_alive[[2]][[1]]), Game4 <- rownames(Chars_alive[[2]][[2]]))

也许直接制作一个新列表会起作用,但如果是这种情况,我想保留原始列表的结构,即 FEB_games > GAME1、GAME2 和 MAR_games > GAME3、GAME4。此外,我更愿意保持列表名称相同,即 GAME1、GAME2、GAME3 和 GAME4。


理想的输出是数据框:

    GAME1    GAME2    GAME3    GAME4
1   Stan     Kenny    Stan     Kenny
2   Kenny    Cartman  Kenny    Cartman
3   Cartman  Kyle     Cartman  Kyle 
4   Kyle     Butters  Butters  Butters
5   Butters   

或列表:

Listname
    FEB_games
        GAME1
           'Stan', 'Kenny', 'Cartman', 'Kyle', 'Butters'
        GAME2
           'Kenny', 'Cartman', 'Kyle', 'Butters'
    MAR_games
        GAME3
            'Stan', 'Kenny', 'Cartman', 'Butters'
        GAME4
            'Kenny', 'Cartman', 'Kyle', 'Butters'

【问题讨论】:

    标签: r list dataframe for-loop


    【解决方案1】:

    你好,我会像这样在 lapply 中使用 lapply。我将您的列表称为“list_games”。

    lapply(list_games, function(x){lapply(x, row.names)})
    

    这给了你

    $FEB_games
    $FEB_games$GAME1
    [1] "Stan"    "Kenny"   "Cartman" "Kyle"    "Butters"
    
    $FEB_games$GAME2
    [1] "Kenny"   "Cartman" "Kyle"    "Butters"
    
    
    $MAR_games
    $MAR_games$GAME3
    [1] "Stan"    "Kenny"   "Cartman" "Butters"
    
    $MAR_games$GAME4
    [1] "Kenny"   "Cartman" "Kyle"    "Butters"
    

    如果行名的长度相同,则可以将其保存为 data.frame

    do.call("rbind.data.frame", lapply(list_games, function(x){lapply(x, row.names)}))
    

    这在这里不起作用,因为行名的长度不同。在这种情况下,您可以执行以下操作:

    res <- sapply(list_games, function(x){lapply(x, row.names)})
    n.obs <- sapply(res , length)
    seq.max <- seq_len(max(n.obs))
    df <- data.frame(t(sapply(res, "[", i = seq.max)))
    df
         X1      X2      X3      X4      X5
    1  Stan   Kenny Cartman    Kyle Butters
    2 Kenny Cartman    Kyle Butters    <NA>
    3  Stan   Kenny Cartman Butters    <NA>
    4 Kenny Cartman    Kyle Butters    <NA>
    

    如果您需要进一步解释,请告诉我。最后一部分是像here

    【讨论】:

    • 我真的需要学习 lapply,这是一个绝妙的解决方案!干杯
    • 我认为 lapply 对整个列表 (x) 执行功能(在本例中为 row.names)是否正确?
    • 使用 lapply 你可以对每个列表应用一个函数。在您的情况下,每个列表都包含一个带有数据框的列表,这就是为什么我在 lapply 内部使用 lapply ,它将函数 row.names 应用于每个数据框。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 2021-11-30
    相关资源
    最近更新 更多