【问题标题】:How to group a vector into a list of vectors?如何将向量分组到向量列表中?
【发布时间】:2014-02-25 07:19:31
【问题描述】:

我有一些看起来像这样的数据(例如假数据):

dressId        color 
6              yellow 
9              red
10             green 
10             purple 
10             yellow 
12             purple 
12             red 

其中颜色是因子向量。不能保证该因子的所有可能级别都实际出现在数据中(例如,颜色“蓝色”也可能是级别之一)。

我需要一个向量列表,对每件衣服的可用颜色进行分组:

[[1]]
yellow  

[[2]] 
red    

[[3]] 
green purple yellow 

[[4]] 
purple red 

保留裙子的 ID 会很好(例如,一个数据框,此列表是第二列,ID 是第一列),但不是必需的。

我写了一个循环,它遍历数据帧的每一行,当下一个 ID 相同时,它将颜色添加到向量中。 (我确信数据是按 ID 排序的)。当第一列中的 ID 发生变化时,它会将向量添加到列表中:

result <- NULL 
while(blah blah) 
{
    some code which creates the vector called "colors" 
    result[[dressCounter]] <- colors 
    dressCounter <- dressCounter + 1
}

在努力使所有必要的计数变量都正确之后,我沮丧地发现它不起作用。第一次,colors

[1] yellow
Levels: green yellow purple red blue

它被强制转换成一个整数,所以result 变成了2

在第二次循环重复中,colors 只包含红色,result 变成了一个简单的整数向量,[1] 2 4

在第三次重复中,colors 现在是一个向量,

[1] green  purple yellow
Levels: green yellow purple red blue 

我得到了

result[[3]] <- colors

结果错误[[3]] 提供的元素多于替换的元素

我做错了什么?有没有办法初始化result,所以它不会被转换为数字向量,而是成为向量列表?

另外,除了“自己动手”之外,还有其他方法可以做到这一点吗?

【问题讨论】:

    标签: r list vector grouping


    【解决方案1】:

    split.data.frame 是一个很好的组织方式;然后提取颜色分量。

    d <- data.frame(dressId=c(6,9,10,10,10,12,12),
                   color=factor(c("yellow","red","green",
                                  "purple","yellow",
                                  "purple","red"),
                     levels=c("red","orange","yellow",
                              "green","blue","purple")))
    

    我觉得你想要的版本其实是这样的:

    ss <- split.data.frame(d,d$dressId)
    

    您可以通过提取颜色分量来获得更像您请求的列表的内容:

    lapply(ss,"[[","color")
    

    【讨论】:

    • +1 如果只是他们想要的列表(从描述中不清楚)也许最好直接使用split 并跳过lapply 步骤。
    • 从描述中,“我需要一个向量列表来对可用颜色进行分组”,也许split(d$color, d$dressId)split(as.character(d$color), d$dressId) 就足够了。
    【解决方案2】:

    除了split,您还应该考虑aggregate。使用cI 作为聚合函数来获取您的list 列:

    out <- aggregate(color ~ dressId, mydf, c)
    out
    #   dressId                 color
    # 1       6                yellow
    # 2       9                   red
    # 3      10 green, purple, yellow
    # 4      12           purple, red
    str(out)
    # 'data.frame': 4 obs. of  2 variables:
    #  $ dressId: int  6 9 10 12
    #  $ color  :List of 4
    #   ..$ 0: chr "yellow"
    #   ..$ 1: chr "red"
    #   ..$ 2: chr  "green" "purple" "yellow"
    #   ..$ 3: chr  "purple" "red"
    out$color
    # $`0`
    # [1] "yellow"
    # 
    # $`1`
    # [1] "red"
    # 
    # $`2`
    # [1] "green"  "purple" "yellow"
    # 
    # $`3`
    # [1] "purple" "red" 
    

    注意:即使“颜色”变量是 factor,这也有效,就像 Ben 的示例数据一样(我在上面发布答案时错过了这一点) 但你需要使用I 作为聚合函数而不是c:

    out <- aggregate(color ~ dressId, d, I)
    str(out)
    # 'data.frame': 4 obs. of  2 variables:
    #  $ dressId: num  6 9 10 12
    #  $ color  :List of 4
    #   ..$ 0: Factor w/ 6 levels "red","orange",..: 3
    #   ..$ 1: Factor w/ 6 levels "red","orange",..: 1
    #   ..$ 2: Factor w/ 6 levels "red","orange",..: 4 6 3
    #   ..$ 3: Factor w/ 6 levels "red","orange",..: 6 1
    out$color
    # $`0`
    # [1] yellow
    # Levels: red orange yellow green blue purple
    # 
    # $`1`
    # [1] red
    # Levels: red orange yellow green blue purple
    # 
    # $`2`
    # [1] green  purple yellow
    # Levels: red orange yellow green blue purple
    # 
    # $`3`
    # [1] purple red   
    # Levels: red orange yellow green blue purple
    

    然而,奇怪的是,默认显示显示的是整数值:

    out
    #   dressId   color
    # 1       6       3
    # 2       9       1
    # 3      10 4, 6, 3
    # 4      12    6, 1
    

    【讨论】:

    • 如何获取字符串而不是整数值?
    【解决方案3】:

    假设你的数据框保存在一个名为df的变量中,那么你可以简单地使用group_bysummarizelist函数的dplyr这样的包

    library('dplyr')
    
    df %>%
      group_by(dressId) %>%
      summarize(colors = list(color))
    

    应用于您的示例:

    df <- tribble(
      ~dressId, ~color,
             6, 'yellow',
             9, 'red',
            10, 'green',
            10, 'purple',
            10, 'yellow',
            12, 'purple',
            12, 'red'
    )
    
    df %>%
      group_by(dressId) %>%
      summarize(colors = list(color))
    
    # dressId                colors
    #       6                yellow
    #       9                   red
    #      10 green, purple, yellow
    #      12           purple, red
    

    【讨论】:

      【解决方案4】:

      恐怕答案应该有点不同,你应该使用下面的代码来完成请求的行为

      df %>%
      group_by(dressId) %>%
      summarize(colors = toString(unique(color)))
      

      【讨论】:

      • 这将创建一个字符串,问题是要求list
      猜你喜欢
      • 2015-03-31
      • 2014-02-18
      • 1970-01-01
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多