【问题标题】:Converting a list-type column to a long form by separating items通过分隔项目将列表类型的列转换为长格式
【发布时间】:2017-12-31 03:45:03
【问题描述】:

我有一个表,其中包含两个感兴趣的列,如下所示:

Status_id |标签
947306525726527488 | NEWYEARSEVEPARTY919
947306316959281153 | MakeItA生活方式
947306315952611330 | c("Ejuice", "vape", "vaping")
947306265520328704 | c(“vapefam”,“vapenation”,“vapefamily”)
947305941522771968 |正在播放

str(juice) #df name
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   5 obs. of  2 variables:
$ status_id: chr  "947306525726527488" "947306316959281153" 
"947306315952611330" "947306265520328704" 
$ hashtags :List of 5
..$ : chr "NEWYEARSEVEPARTY919"
..$ : chr "MakeItALifestyle"
..$ : chr  "Ejuice" "vape" "vaping" "eliquid"
..$ : chr  "vapefam" "vapenation" "vapefamily"
..$ : chr "nowplaying"

数据

structure(list(status_id = c("947306525726527488", "947306316959281153", 
"947306315952611330", "947306265520328704", "947305941522771968"
), hashtags = list("NEWYEARSEVEPARTY919", "MakeItALifestyle", 
    c("Ejuice", "vape", "vaping", "eliquid", "ecigjuice", "ecig", 
    "vapejuice"), c("vapefam", "vapenation", "vapefamily", "vapelife", 
    "vapelyfe", "vapeon", "positivity"), "nowplaying")), .Names = c("status_id", 
"hashtags"), row.names = c(NA, -5L), class = c("tbl_df", "tbl", 
"data.frame"))

预期结果

我想要以下两个表(当然在实际的原始 df 中,我删除了更多列,因为它们与问题无关):

df1
状态_id
947306525726527488
947306316959281153
947306315952611330
947306265520328704
947305941522771968

df2
status_id |标签
947306525726527488 | NEWYEARSEVEPARTY919
947306316959281153 | MakeItA生活方式
947306315952611330 |果汁
947306315952611330 |电子烟
947306315952611330 |电子烟
947306265520328704 |电子烟
947306265520328704 |汽化
947306265520328704 |电子烟
947305941522771968 |正在播放

原始数据每个 status_id 有一行,所有主题标签 >1 为 c(...) - 归类为类型:“列表”。 df2 将各个主题标签分成单独的行。

虽然我以前从未遇到过列表类型的列,但在谷歌上搜索它让我得到了很多关于将列表转换为列而不是“列表”类型的列的内容

【问题讨论】:

  • 如果您的原始数据集是df2,可能类似于df1 <- df2[, 1, drop = F]
  • original 是 str() 代码上方的最顶层表格。 df1 和 df2 是期望的结果
  • 你的原始数据和df2有什么区别?
  • 原始数据每个 status_id 有一行,所有主题标签为 c(...) - 归类为类型:“列表”。 df2 将各个主题标签分成单独的行
  • 知道了。所以,df1:- df1 <- original[, 1, drop = F] 应该可以工作。

标签: r dataframe split


【解决方案1】:

这是一种可能的解决方案。我打电话给你的数据mydf。您在hashtags 中有列表。您可以使用unlist()paste()hashtags 中的每一行创建一个向量。如果需要,可以使用 toSting() 代替 paste()。一旦你在hashtags 中有一个向量,你就想拆分它。具体来说,对于第 3 行和第 4 行,您有多个主题标签。你想把它们分开。您可以使用 splitstackshape 包中的 cSplit()。结果就是你想要的df2。一旦你有了它,你想创建df1。您选择status_id 并寻找唯一的status_id

library(dplyr)
library(splitstackshape)

df2 <- mydf %>%
       rowwise %>%
       mutate(hashtags = paste(unlist(hashtags), collapse = ",")) %>%
       cSplit(splitCols = "hashtags", sep = ",", direction = "long")

             status_id            hashtags
 1: 947306525726527488 NEWYEARSEVEPARTY919
 2: 947306316959281153    MakeItALifestyle
 3: 947306315952611330              Ejuice
 4: 947306315952611330                vape
 5: 947306315952611330              vaping
 6: 947306315952611330             eliquid
 7: 947306315952611330           ecigjuice
 8: 947306315952611330                ecig
 9: 947306315952611330           vapejuice
10: 947306265520328704             vapefam
11: 947306265520328704          vapenation
12: 947306265520328704          vapefamily
13: 947306265520328704            vapelife
14: 947306265520328704            vapelyfe
15: 947306265520328704              vapeon
16: 947306265520328704          positivity
17: 947305941522771968          nowplaying

df1 <- unique(df2[, 1, with = FALSE])

            status_id
1: 947306525726527488
2: 947306316959281153
3: 947306315952611330
4: 947306265520328704
5: 947305941522771968

修订

感谢splitstackshape 包作者的评论,我们找到了更好的方法来处理这个任务。 listCol_l() 是将作为列表存储的列取消列出为长格式的函数。因此,所有必要的过程都可以在一条线上完成。

df2 <- listCol_l(mydf, "hashtags") 

【讨论】:

  • 完美运行 - 将此作为最简单的最佳答案
  • @SaleemKhan 很高兴为您提供帮助。 :)
  • @SaleemKhan,既然你已经在使用“tidyverse”,你就不能做unnest(juice)吗?
  • 或者,使用“splitstackshape”,listCol_l(juice, "hashtags")[] :-)
  • @A5C1D2H2I1M1N2O1R2T1 我明白了。帽子很吸引人,不是吗? :) 如果我能提供任何帮助,我很乐意帮助您进行更新。
【解决方案2】:
library(data.table)
library(dplyr)

rm(list=ls())

k <- c(LETTERS[1:5])
v <- list('a','b', c('c','d','e'), c('f','g'), 'h')
df <- cbind(k, v) %>% as.data.frame(df)
df

df.temp <- df %>% mutate(vn = sapply(v, length)) 
k <- rep(df.temp$k, df.temp$vn, each=TRUE) %>% unlist
v <- unlist(df.temp$v)

df2 <- data.frame(k, v)
df1 <- df$k %>% unlist %>% data.frame(k=.)

df1
df2
  • 结果


【讨论】:

  • 很好的想法来解决问题。
【解决方案3】:

为了完整起见,这里也是data.table的解决方案:

library(data.table)
df2 <- setDT(juice)[, .(hashtag = unlist(hashtags)), by = status_id]
df1 <- unique(juice[, .(status_id)])

df2
             status_id             hashtag
 1: 947306525726527488 NEWYEARSEVEPARTY919
 2: 947306316959281153    MakeItALifestyle
 3: 947306315952611330              Ejuice
 4: 947306315952611330                vape
 5: 947306315952611330              vaping
 6: 947306315952611330             eliquid
 7: 947306315952611330           ecigjuice
 8: 947306315952611330                ecig
 9: 947306315952611330           vapejuice
10: 947306265520328704             vapefam
11: 947306265520328704          vapenation
12: 947306265520328704          vapefamily
13: 947306265520328704            vapelife
14: 947306265520328704            vapelyfe
15: 947306265520328704              vapeon
16: 947306265520328704          positivity
17: 947305941522771968          nowplaying
df1
            status_id
1: 947306525726527488
2: 947306316959281153
3: 947306315952611330
4: 947306265520328704
5: 947305941522771968

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多