【问题标题】:Aggregating by unique identifier and concatenating related values into a string [duplicate]按唯一标识符聚合并将相关值连接成一个字符串[重复]
【发布时间】:2013-05-11 21:10:34
【问题描述】:

我认为aggregatereshape 可以满足我的需求,但我不太清楚。

我有一个姓名列表 (brand) 和随附的 ID 号 (id)。该数据是长格式的,因此名称可以有多个 ID。我想按名称 (brand) 进行重复数据删除,并将多个可能的 id 连接成一个由注释分隔的字符串。

例如:

brand            id 
RadioShack       2308
Rag & Bone       4466
Ragu             1830
Ragu             4518
Ralph Lauren     1638
Ralph Lauren     2719
Ralph Lauren     2720
Ralph Lauren     2721
Ralph Lauren     2722 

应该变成:

RadioShack       2308
Rag & Bone       4466
Ragu             1830,4518
Ralph Lauren     1638,2719,2720,2721,2722

我将如何做到这一点?

【问题讨论】:

  • 在你想要的输出中,“Ragu”不应该出现两次,对吧?
  • 对于每个品牌,您希望结果是 list 的 id 还是一个拼凑在一起的字符串?

标签: r concatenation aggregate


【解决方案1】:

让我们调用你的 data.frame DF

> aggregate(id ~ brand, data = DF, c)
         brand                           id
1   RadioShack                         2308
2   Rag & Bone                         4466
3         Ragu                   1830, 4518
4 Ralph Lauren 1638, 2719, 2720, 2721, 2722

使用aggregate 的另一种选择是:

result <- aggregate(id ~ brand, data = DF, paste, collapse = ",")

这会产生相同的结果,现在id 不再是list。感谢@Frank 评论。要查看每列的class,请尝试:

> sapply(result, class)
      brand          id 
   "factor" "character"

正如@DavidArenburg 在 cmets 中提到的,另一种选择是使用 toString 函数:

aggregate(id ~ brand, data = DF, toString)

【讨论】:

  • 很奇怪,R 不允许我输出这个 data.frame...我想是因为 id 是一个列表。如何导出到 CSV?
  • @Jilber 你的“id”输出列的类应该是“字符”(不是列表),我认为,因为 OP 想要导出数据框。
  • +1。我喜欢这个解决方案,供我自己使用。不过,对于 OP 的问题,我认为您可能希望将其更改为 aggregate(id~brand,paste,collapse=",",data=df) 或类似名称。
  • 很可能值得一提aggregate(id ~ brand, DF, toString)
  • 如果我想做同样的事情但只针对特定价值会发生什么?我的意思是,在你的例子中只有id==2308
【解决方案2】:

data.table 中的一行很干净

library(data.table)
setDT(DF)

两个选项:

结果为列表

DF[ , .(id = list(id)), by = brand]
          brand                       id
1:   RadioShack                     2308
2:   Rag & Bone                     4466
3:         Ragu                1830,4518
4: Ralph Lauren 1638,2719,2720,2721,2722
> 

结果为字符串

DF[ , .(id = paste(id, collapse=",")), by = brand]
          brand                       id
1:   RadioShack                     2308
2:   Rag & Bone                     4466
3:         Ragu                1830,4518
4: Ralph Lauren 1638,2719,2720,2721,2722

注意

尽管两个结果看起来相同(即当您打印它们时,它们看起来相同),但它们实际上非常不同并且允许不同的功能。

也就是说,使用列表选项(第一个)允许您在原始ids 上执行功能。

后者可以让您更轻松地显示信息(包括导出到CSVexcel),但要对id 进行操作则需要将它们拼接回去。

【讨论】:

  • 谢谢! list(list(id)) 有效,但为什么呢?
  • @LauriK, list(list(id)) 与答案中的第一个选项相同。唯一的区别是列表中的名称是否明确给出。外部list, data.table 将翻译成“列”的意思(因为所有的 data.tables 和 data.frames 实际上只是列的列表)。内部list表示每个单元格中的值将是一个列表
  • 谢谢!我正在使用paste(id, sep = ",") 并最终得到未汇总的结果。事实证明,我需要改用paste(id, collapse = ",")
【解决方案3】:

或者使用dplyr:

library(dplyr)
DF %>%
  group_by(brand) %>%
  summarise(id = paste(id, collapse = ","))

DF 是您的 data.frame 的名称。

【讨论】:

  • 这将使汇总列成为逗号分隔的字符串类型。不是向量...
  • 不,就像在其他答案中一样,结果是一个data.frame,带有一个名为id 的向量,属于character 类,包含id 的字符串,根据需要用逗号分隔这个问题。 is.vector(DF$id) 返回TRUE。如果您对此方法有任何疑问,请考虑将其作为新问题发布。
  • library(dplyr) DFNew% group_by(brand) %>% summarise(id=unique(list(id))) 这对我有用
  • @SamFirke,您能否建议我如何使用您的解决方案仅粘贴 id 的唯一值,而 id 的重复值对应于 brand?谢谢!
  • 尝试添加unique,改成paste(unique(id), collapse = ",") - 如果不这样做,值得发布一个新问题。
【解决方案4】:

这是base R中的信息:

myby <- by(df$id,df$brand,function(x)paste(x,collapse=","))

“by”对象的格式很奇怪。您可以使用data.frame(id=c(myby)),品牌将成为行名:

#                                    id
# RadioShack                       2308
# Rag & Bone                       4466
# Ragu                        1830,4518
# Ralph Lauren 1638,2719,2720,2721,2722

或者,如果您加载 data.table 包,这将起作用:

dt <- data.table(df)
dt[,paste(id,collapse=","),by=brand]
#           brand                       V1
# 1:   RadioShack                     2308
# 2:   Rag & Bone                     4466
# 3:         Ragu                1830,4518
# 4: Ralph Lauren 1638,2719,2720,2721,2722

【讨论】:

    猜你喜欢
    • 2020-12-07
    • 2012-04-02
    • 2021-01-22
    • 2021-11-24
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    相关资源
    最近更新 更多