在 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 中重新组织数据的主要内容,如果未能解决你的问题,请参考以下文章