首页 > 解决方案 > 使用从 R 上的另一列中提取的信息创建新列

问题描述

我有一个数据框,其中一列有几个由“;”分隔的信息,如下所示:

DF = data.frame(a = c(1,1,1,2,2), b = c('aaa','aaa','aba','abc','ccc'), 
                extra_info = c(
                  'animal=horse;color=orange;shape=circle',
                  'animal=monkey;shape=square;value=532',
                  'animal=horse;color=blue;shape=square;value=321',
                  'animal=dog;color=green;value=678',
                  'color=pink;shape=triangle'
                ))

我不能使用 read.table 因为我已经在使用不同的函数来读取数据(而且列 extra_info 中每一行的内容也不同,并且列会被弄乱)。我想做的是将所有这些信息分开到不同的列,并相应地分配适当的名称,例如:

a   b   animal  color   shape    value
1  aaa  horse   orange  circle   NA
1  aaa  monkey  NA      square   532
1  aba  horse   blue    square   321
2  abc  dog     green   NA       678
2  ccc  NA      pink    triangle NA

到目前为止,我已经尝试过:

new_cols = DF %>% separate(extra_info, c(LETTERS[1:4]), sep = ";")

new_cols %>% separate(A, c("key","value"), sep = '=') %>% 
  separate(B, c("key","value"), sep = '=') %>%
  separate(C, c("key","value"), sep = '=') %>%
  separate(D, c("key","value"), sep = '=') %>%
  pivot_wider(names_from = c("key"), values_from = c("value"))

但它没有按预期工作。

标签: rstringdplyrtidyverseextract

解决方案


这是使用gsub+ eval+的基本 R 选项str2expression

v <- DF$extra_info
p <- gsub(";", ",", gsub("(?<=\\=)(\\w+)", "'\\1'", v, perl = TRUE))
nms <- unique(unlist(regmatches(v, gregexpr("\\w+(?=\\=)", v, perl = TRUE))))
q <- unname(Map(function(x) setNames(eval(str2expression(x))[nms], nms), sprintf("c(%s)", p)))
cbind(DF[c("a","b")], type.convert(data.frame(do.call(rbind, q)), as.is = TRUE))

这使

  a   b animal  color    shape value
1 1 aaa  horse orange   circle    NA
2 1 aaa monkey   <NA>   square   532
3 1 aba  horse   blue   square   321
4 2 abc    dog  green     <NA>   678
5 2 ccc   <NA>   pink triangle    NA

推荐阅读