【问题标题】:Split dataframe column of separated key-value pairs into new columns [duplicate]将分离的键值对的数据框列拆分为新列[重复]
【发布时间】:2018-12-20 21:27:03
【问题描述】:

我有一个包含 5 列的数据框,其中 4 列是“正常”值,第 5 列是一组分隔符分隔的键值对,格式为

key1 = value1 | key2 = value2 | key3 = value3

单行中没有重复的键,但不能保证它们在每行中的顺序相同,或者每行中键/值对的数量相同。

将值放入 ~15 列并为其键正确命名的最简单方法是什么?

【问题讨论】:

  • 请分享dput(head(your_dataframe_here)) 的输出以使您的问题可重现。还显示预期输出和您自己尝试过的内容。
  • @Mako212 不完全是骗子,数据格式不同。
  • 这是一个常见问题,适用于包含由键值对组成的单列的大型数据帧。请参阅我在下面提供的示例数据,以及一个干净的基于 dplyr 的解决方案。
  • @Mako212 这不应被标记为重复。这个问题询问如何分解数据框中存在的键值对列。另一个询问有关读取包含此类字段的文件。

标签: r key-value


【解决方案1】:

这是一个替代方案,它将使用 tidyr、dplyr 和 stringr 保持非键值列的完整性。

创建测试数据

testdf <- data_frame(col1 = paste0("a", 1:4), col2 = paste0("b", 1:4), 
              col3 = paste0("c", 5:8),
              col4 = paste0("enst", 12099:12102),
              col5 = c("bang=1 | dong=2 | foo=6", "bang=2 | dong=3 | zups=foo", 
                       "dimbo=2 | bang=6 | jumbo=7 | zoo=camel", "boo=0"))

代码

library(stringr)
library(tidyr)
library(dplyr)

KVsep <- fixed(" | ")  #key-value separator
Vsep <- fixed("=")     #value separator

newDF <-  testdf %>%
  mutate(KVpairs = str_split(col5, KVsep)) %>%
  unnest(KVpairs) %>%
  separate(KVpairs, into = c("key", "value"), Vsep) %>%
  spread(key, value) %>%
  select(-col5)

结果

> newDF
# A tibble: 4 x 12
  col1  col2  col3  col4      bang  boo   dimbo dong  foo   jumbo zoo   zups 
* <chr> <chr> <chr> <chr>     <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 a1    b1    c5    enst12099 1     NA    NA    2     6     NA    NA    NA   
2 a2    b2    c6    enst12100 2     NA    NA    3     NA    NA    NA    foo  
3 a3    b3    c7    enst12101 6     NA    2     NA    NA    7     camel NA   
4 a4    b4    c8    enst12102 NA    0     NA    NA    NA    NA    NA    NA
> 

【讨论】:

    【解决方案2】:

    好吧,我不认为有任何专门的功能可以解决这个问题,但稍微编程一点也不复杂。

    c2nv <- function(x){
      # part 1 - convert vector to name-value pairs
      x <- strsplit(x, "|", fixed=TRUE) # split at |, then split at =
      x <- sapply(x,  function(.) t(trimws(sapply(lapply(., strsplit, "="), "[[", 1))))
      x1 <- lapply(x, function(.) setNames( .[,2], .[,1]))
      # part 2 - find all existing names in all rows
      u <- sort(unique(unlist(lapply(x1, names))))  # unique keys
      res <- t(sapply(x1, function(.) .[u]))   # look at each key in each row
      colnames(res) <- u
      res
    }
    

    样本数据

    col <- c("bang=1 | dong = 2 | foo = 6", "bang1=2 | dong = 3 | zups = foo", 
    "dimbo = 2 | bang = 6 | jumbo = 7 | zoo = camel", "boo = 0")
    

    处理样本数据

    > c2nv (col)
         bang bang1 boo dimbo dong foo jumbo zoo     zups 
    [1,] "1"  NA    NA  NA    "2"  "6" NA    NA      NA   
    [2,] NA   "2"   NA  NA    "3"  NA  NA    NA      "foo"
    [3,] "6"  NA    NA  "2"   NA   NA  "7"   "camel" NA   
    [4,] NA   NA    "0" NA    NA   NA  NA    NA      NA   
    > 
    

    【讨论】:

    • 这很棒。假设每个键只能出现一次,有没有办法将每行的输出扁平化为一行?
    • 嗨,我不确定我是否理解 - 你能解释一下你期望的输出是什么样的吗?
    • 对不起,我误读了您的回复,它按预期工作。再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 2014-12-04
    • 2018-10-31
    • 2013-04-21
    • 2022-01-09
    • 1970-01-01
    相关资源
    最近更新 更多