在 r 中重新组织数据

Posted

技术标签:

【中文标题】在 r 中重新组织数据【英文标题】:Reorganise Data in r 【发布时间】:2022-01-02 20:09:21 【问题描述】:

例如,我有一张桌子:

House,Name1,Email1@xyz.com
Flat,Name2;Name3,Email2@xyz.com;Email3@xyz.com
Mobile Home,Name4,Email4@xyz.com
Camper-Van,Name5;Name6;Name7;Name8,Email5@xyz.com;Email6@xyz.com;Email7@xyz.com;Email8@xyz.com

我需要:

House,Name1,Email1@xyz.com
Flat,Name2,Email2@xyz.com
Flat,Name3,Email3@xyz.com
Mobile Home,Name4,Email4@xyz.com
Camper-Van,Name5,Emil5@xyz.com
Camper-Van,Name6,Email6@xyz.com
Camper-Van,Name7,Email7@xyz.com
Camper-Van,Name8,Email8@xyz.com

问题是,一种住房的姓名和电子邮件数量是未知的。

我生成了三个列表:

Housing:      
House
Flat
Campervan 

Names:
Name1
Name2
Name3
Name4
Name5
Name6
Name7
Name8

Email:
Email1@xyz.com
Email2@xyz.com
...
Email8@xyz.com

但是我被困在如何重复 House 和 Flat 和 Campervan,因为第 1 列中每个类别的名称或电子邮件(两者总是完全相同的数量)。这将使所有 List 在长度上相互匹配。

如果我能够做到这一点,我就可以生成我需要的信息。 任何帮助表示赞赏。

注意:姓名和电子邮件地址不一样,例如 Name1 是 hans,他的电子邮件可能是 Peter@foo.org,通过对姓名和电子邮件进行编号,我确实试图表明电子邮件和姓名是排序的,不能随机入伍

【问题讨论】:

我假设您只有一个电子邮件列表,例如 foo@bar.com,而不是 Email8,您想提取这些模式对吗? 是的,但姓名和电子邮件不匹配:( 根据您的示例数据,可以分别映射姓名和电子邮件,例如(name1, name2) -> (email@1, email@2) 是的,我的错我必须澄清这一点,而且我不得不编辑我的露营车以显示一些困难。我确实尝试实施您的解决方案,但被卡住了,所以很明显我确实错过了指出一些事情 我相应地更新了我的答案 【参考方案1】:
library(tidyverse)

example_text <-"House,Name1,Email@1
Flat,Name2;Name3,Email@2;Email@3
Mobile Home,Name4,Email@4
Camper-Van,Name5;Name6;Name7;Name8,Email@5;Email@6;Email@7;Email@8
"
example_text %>%
  read_lines() %>%
  map(~ 
    # the first words until a delimiter
    house <- .x %>% str_extract("^[^;,]+")
    elements <- .x %>% str_remove(house) %>% str_split("[,;]") %>% simplify() %>% discard(~ .x == "")
    # Everything with an @ symbol betwwen two demiliters (, or ;)
    Emails <- elements %>% keep(~ .x %>% str_detect("@"))
    # Everything which is not one of the above
    Names <- elements %>% setdiff(Emails)
    
    tibble(
      House = house,
      Emails = Emails,
      Names = Names
    )
  ) %>%
  reduce(bind_rows)
#> # A tibble: 8 x 3
#>   House       Emails  Names
#>   <chr>       <chr>   <chr>
#> 1 House       Email@1 Name1
#> 2 Flat        Email@2 Name2
#> 3 Flat        Email@3 Name3
#> 4 Mobile Home Email@4 Name4
#> 5 Camper-Van  Email@5 Name5
#> 6 Camper-Van  Email@6 Name6
#> 7 Camper-Van  Email@7 Name7
#> 8 Camper-Van  Email@8 Name8

由reprex package (v2.0.1) 于 2021 年 11 月 24 日创建

【讨论】:

我会试一试,谢谢伙计【参考方案2】:

使用 data.table 中的数据(使用 setDT() 转换),使用 data.table 连接和 data.table tstrsplit() 函数:

library(data.table)
# Data for the demo (please provide this yourself in future questions)
dt1 <-
  data.table(type = c("House", "Flat", "Mobile", "Camper-van"),
             name = c("Name1", "Name2;Name3", "Name4", "Name5;Name6;Name7;Name8"),
             mail = c("Email1", "Email2;Email3", "Email4", "Email5;Email6;Email7;Email8"))

# solution
dt1[, c("type" = list(type), tstrsplit(name, ";"))][, melt(.SD, id.vars="type")][!is.na(value), .(.I, type, "name" = value)][
  dt1[, c("type" = list(type), tstrsplit(mail, ";"))][, melt(.SD, id.vars="type")][!is.na(value), .(.I, "mail" = value)], on="I"][, -c("I")]

【讨论】:

请注意,如果存在没有电子邮件地址的名称,则此解决方案将失效,反之亦然(例如,您有 name3 但没有 email3)

以上是关于在 r 中重新组织数据的主要内容,如果未能解决你的问题,请参考以下文章

R中的重新排序和重塑列[重复]

——R的数据组织

——R的数据组织

在 C++ 中重新组织缓冲区中数据的有效方法

重新组织 vs 重新生成索引

10-07重新生成和组织索引