【问题标题】:Split string bewteen words and semicolon in r在r中的单词和分号之间拆分字符串
【发布时间】:2020-02-14 20:03:00
【问题描述】:

我在名为text 的列中有一个包含字符串的数据框(或数据表),如下所示:

text
name: john; surname: smith; age: 35; gender:male
name: mark; age:50
name: jack; surname: brown
name: tom; surname: travis; gender: male

如何将字符串的每个部分提取到同一数据框中的单独列中?我想要以下列:

name.text
name: john
name: mark
name: jack
name: tom

surname.text
surname: smith
(empty)
surname: brown
surname: travis

age.text
age: 35
age: 50
(empty)
(empty)

gender.text
gender:male
(empty)
(empty)
gender:male

谢谢!

【问题讨论】:

    标签: r string dataframe parsing data.table


    【解决方案1】:

    这是一种选择,我们将; 处的元素拆分,然后将separate 分成两列,并从“长”格式重新调整为“宽”格式

    library(dplyr)
    library(tidyr)
    library(stringr)
    library(tibble)
    df1 %>%
       rownames_to_column('rn') %>%
       separate_rows(text, sep = ';\\s*') %>%
       separate(text, into = c('key', 'val'), sep=":\\s*") %>% 
       pivot_wider(names_from = key, values_from = val, 
                values_fill = list(val = "(empty)")) %>%
       select(-rn) %>%
       imap_dfr(~ case_when(.x != "(empty)" ~ str_c(.y, .x, sep=":"), TRUE ~ .x)) %>%
       rename_all(~ str_c(., ".text"))
    # A tibble: 4 x 4
    #  name.text surname.text   age.text gender.text
    #  <chr>     <chr>          <chr>    <chr>      
    #1 name:john surname:smith  age:35   gender:male
    #2 name:mark (empty)        age:50   (empty)    
    #3 name:jack surname:brown  (empty)  (empty)    
    #4 name:tom  surname:travis (empty)  gender:male
    

    或者使用base R

    nm1 <- c("name", "surname", "age", "gender")
    lst1 <-  lapply(strsplit(df1$text, ";\\s*"), function(x) {
              prfx <- sub(":.*", "", x)
              x1 <- x[match(nm1, prfx)]
              replace(x1, is.na(x1), "(empty)")})
    out <- do.call(rbind.data.frame, lst1)
    names(out) <- paste0(nm1, ".text")
    out
    #   name.text    surname.text age.text  gender.text
    #1 name: john  surname: smith  age: 35  gender:male
    #2 name: mark         (empty)   age:50      (empty)
    #3 name: jack  surname: brown  (empty)      (empty)
    #4  name: tom surname: travis  (empty) gender: male
    

    数据

    df1 <- structure(list(text = c("name: john; surname: smith; age: 35; gender:male", 
    "name: mark; age:50", "name: jack; surname: brown", 
    "name: tom; surname: travis; gender: male"
    )), class = "data.frame", row.names = c(NA, -4L))
    

    【讨论】:

    • 非常感谢您的回复。我需要使用几乎基本的 R (因为其他项目依赖,不要问为什么:))。你能帮忙吗,如何仅使用基础 R 来解决这个问题?
    • @Makaroni。在帖子中,你指定了data.table(所以你在使用那个包)
    • @Makaroni。更新为base R
    【解决方案2】:
    d = lapply(strsplit(df1$text, "; ?"), function(x){
        data.frame(do.call(rbind, strsplit(x, ": ?")), stringsAsFactors = FALSE)
    })
    
    fields = unique(unlist(lapply(d, function(x) x$X1)))
    
    d2 = do.call(rbind, lapply(d, function(x)
        data.frame(fields, val = x$X2[match(fields, x$X1)])))
    
    d2[order(match(d2$fields, fields)),]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      相关资源
      最近更新 更多