如何在R中将一个单元格拆分为多列

3
这是我的一个列的样子:
信息
姓名:安吉拉 姓氏:史密斯 年龄:22 城市:洛杉矶
姓名:安德鲁 姓氏:D'ONOFRIO 年龄:47 城市:纽约市
我想创建四列:
姓名 姓氏 年龄 城市
安吉拉 史密斯 22 洛杉矶
安德鲁 D'ONOFRIO 47 纽约市
我了解到我们可以使用tidyverse中的“separate”函数,这是我尝试的内容。
library(tidyr)
library(tidyverse)

df <- infos %>% separate(Infos, c("NAME", "SURNAME","AGE","CITY"))


但这是输出结果:

名字 姓氏 年龄 城市
名字 安吉拉 姓氏 史密斯
名字 安德鲁 姓氏 多诺弗里奥

那么我想了解如何让R知道它需要分隔什么。也许这个话题已经在这里被讨论过了(但我没有找到),所以如果需要的话,请随时引导我!

5个回答

6

1) 提取 使用所示的模式来提取数据。即使测试数据字段内容中没有空格,但是即使有空格这个方法也可以正常工作。

library(dplyr)
library(tidyr)

pat <- "NAME: *(.*) SURNAME: *(.*) AGE: *(.*) CITY: *(.*)"
dat %>% 
  extract(Infos, c("NAME", "SURNAME", "AGE", "CITY"), pat, convert = TRUE)
##     NAME   SURNAME AGE CITY
## 1 ANGELA     SMITH  22   LA
## 2 ANDREW D'ONOFRIO  47  NYC

2) Base R 如果只使用base R,我们可以得到下面这个通用解决方案,即使列数或列名发生更改,该解决方案也将继续起作用。即使字段内容中有空格,它也能正常工作。它通过将“ Infos”转换为dcf格式,然后使用read.dcf函数进行读取来实现。

dat |>
  with(gsub("(\\w+:)", "\n\\1", Infos)) |>
  textConnection() |>
  read.dcf() |>
  as.data.frame() |>
  type.convert(as.is = TRUE)
##     NAME   SURNAME AGE CITY
## 1 ANGELA     SMITH  22   LA
## 2 ANDREW D'ONOFRIO  47  NYC

注意

将数据以可重复的形式呈现:

dat <-
structure(list(Infos = c("NAME: ANGELA SURNAME:SMITH AGE:22 CITY: LA", 
"NAME: ANDREW SURNAME: D'ONOFRIO AGE:47 CITY: NYC")), class = "data.frame", row.names = c(NA, 
-2L))

2
一种更多的策略。
df <- structure(list(Infos = c("NAME: ANGELA SURNAME:SMITH AGE:22 CITY: LA", 
                           "NAME: ANDREW SURNAME: D'ONOFRIO AGE:47 CITY: NYC")), class = "data.frame", row.names = c(NA, 
                                                                                                                     -2L))
library(tidyverse)

df %>%
  mutate(Infos = gsub('\\:\\s*', ':', Infos)) %>%
  separate_rows(Infos, sep = '\\s') %>%
  separate(Infos, into = c('N', 'V'), sep = ':') %>%
  pivot_wider(names_from = N, values_from = V, values_fn = list) %>%
  unnest(everything())
#> # A tibble: 2 x 4
#>   NAME   SURNAME   AGE   CITY 
#>   <chr>  <chr>     <chr> <chr>
#> 1 ANGELA SMITH     22    LA   
#> 2 ANDREW D'ONOFRIO 47    NYC

这段文字是由 reprex package (v2.0.0) 于2021年7月15日创建的


2
使用strcapture的基本R选项 -
strcapture('NAME:\\s*(.*)\\s*SURNAME:\\s*(.*)\\s*AGE:\\s*(.*)\\s*CITY:\\s*(.*)', 
           infos$Infos, proto = list(NAME = character(), 
           SURNAME = character(), AGE = numeric(), CITY = character()))

#    NAME    SURNAME  AGE CITY
#1 ANGELA      SMITH   22   LA
#2 ANDREW  D'ONOFRIO   47  NYC

1

这里有一种使用str_squishstr_replace_allseparate的解决方案。

library(dplyr)
library(stringr)
df %>% 
  mutate(Infos = str_squish(str_replace_all(Infos, ":", " "))) %>% 
  separate(Infos, c("helper1", "Name", "helper2", "Surname", "helper3", "Age", "helper4","City"), sep = " ") %>%
  select(-starts_with("helper"))

输出:

  Name   Surname   Age   City 
  <chr>  <chr>     <chr> <chr>
1 ANGELA SMITH     22    LA   
2 ANDREW D'ONOFRIO 47    NYC  

0
你可以插入虚拟列,然后将其删除。
tibble(dat=c("NAME: ANGELA SURNAME:SMITH AGE:22 CITY: LA", 
             "NAME: ANDREW SURNAME: DONOFRIO AGE:47 CITY: NYC")) %>% 
    separate(dat, c("DEL1", "NAME", "DEL2", "SURNAME", "DEL3", "AGE", "DEL4", "CITY")) %>% 
    select(-DEL1, -DEL2, -DEL3, -DEL4)
 NAME   SURNAME  AGE   CITY 
 ANGELA SMITH    22    LA   
 ANDREW DONOFRIO 47    NYC  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接