如何将一行 [“A, B, C”, “7”] 转换为三行 [“A”, “7”], [“B”, “7”], [“C”, “7”]

How to transform a row ["A, B, C", "7"] into three rows ["A", "7"], ["B", "7"], ["C", "7"]

提问人:Thiago Godoy 提问时间:10/28/2023 更新时间:10/28/2023 访问量:72

问:

想象一下下表

埃勒姆 频率
一个 14
甲、乙 7
A、C 8
A、B、C 1
乙、丙 3
B 11
C 6

我怎样才能在隔离每个元素并求和频率的表中转换它。

在这种情况下,将是

术语 频率
一个 30
B 22
C 18

我想写一个巨大的case_when(我有三个以上的元素)来搜索整个表格并汇总它们存在的行的频率,但这已经很多了

我想像这样打破界限:

埃勒姆 频率
一个 14
一个 7
B 7
一个 8
C 8
一个 1
B 1
C 1
B 3
C 3
B 11
C 6

然后将其与频率相加,但我不知道如何

R 字符串 拆分 tidyverse

评论


答:

6赞 ThomasIsCoding 10/28/2023 #1

你可以试试,然后separate_longer_delimsummarise

library(dplyr)
library(tidyr)

df %>%
    separate_longer_delim(Elem, ", ") %>%
    summarise(Freq = sum(Freq), .by = Elem)

您将获得

  Elem Freq
1    A   30
2    B   22
3    C   18

评论

2赞 Jilber Urbina 10/28/2023
separate_rows(Elem, sep=", ")在这种情况下也有效。
0赞 ThomasIsCoding 10/29/2023
@JilberUrbina 是的,这也很好用:)
0赞 Thiago Godoy 10/31/2023
谢谢@ThomasIsCoding和@jilber-urbina!这正是我想要的。
2赞 jay.sf 10/28/2023 #2

使用 和 .strsplitxtabs

> Map(data.frame, strsplit(dat$Elem, ',\\s*'), dat$Freq) |> lapply(setNames, names(dat)) |> 
+   do.call(what='rbind') |> setNames(names(dat)) |> xtabs(Freq ~ Elem, data=_) |> as.data.frame()
  Elem Freq
1    A   30
2    B   22
3    C   18
2赞 Jilber Urbina 10/28/2023 #3

另一个基本 R 解决方案

> tmp <- stack(setNames(strsplit(df$Elem,', '), df$Freq)) 
> tmp[,"ind"] <- as.numeric(as.character(tmp[,"ind"]))
> aggregate(ind ~ values, FUN = sum, data = tmp)
  values ind
1      A  30
2      B  22
3      C  18

数据:

structure(list(Elem = c("A", "A, B", "A, C", "A, B, C", "B, C", 
"B", "C"), Freq = c(14L, 7L, 8L, 1L, 3L, 11L, 6L)), class = "data.frame", row.names = c(NA, 
-7L))