【发布时间】:2019-10-05 12:22:08
【问题描述】:
data 有一个名为 description 类型为 character() 的列和一个类型为 id 的列 integer() 由 row_number() 设置。
data_map 具有 desc_map 类型的 character() 列名称和 id 类型的列 integer() 由 row_number() 设置。
data 和 data_map 在加入后确实有其他列用于进一步处理。
下面代码的想法是使用data_map$desc_map作为str_detect中的模式来匹配data$description。在匹配中,它会使用data$id 和data_map$id 将一行添加到另一个tibble。生成的matches 允许将data 和data_map 连接在一起。
library(tidyverse)
data = tribble(
~description,
"19ABB123456",
"19BCC123456",
"19CDD123456",
"19DEE123456",
"19EFF456789",
"19FF0056789",
"19A0A123456",
) %>% mutate(id = row_number())
data_map = tribble(
~desc_map,
"AA",
"BB",
"CC",
"DD",
"EE",
"FF",
"00",
) %>% mutate(id = row_number())
seq_along_rows <- function(.data) {
seq_len(nrow(.data))
}
matches <- data %>% (function (tbl) {
m <- tibble(
row_id = integer(),
map_id = integer()
)
for (i in seq_along_rows(tbl)) {
row <- tbl[i, ]
key <- row[["description"]]
found <- FALSE
for (j in seq_along_rows(data_map)) {
map_row <- data_map[j, ]
pattern <- map_row[["desc_map"]]
if (str_detect(key, pattern)) {
m <- add_row(m, row_id = row[["id"]], map_id = map_row[["id"]])
found <- TRUE
# allow for finding more than one match
}
}
if (!found) {
m <- add_row(m, row_id = row[["id"]], map_id = NA)
}
}
return(m)
})
not_unique <- matches %>%
group_by(row_id) %>%
filter(n() > 1) %>%
ungroup() %>%
inner_join(data, by = c("row_id" = "id")) %>%
inner_join(data_map, by = c("map_id" = "id"))
head(not_unique)
#> # A tibble: 2 x 4
#> row_id map_id description desc_map
#> <int> <int> <chr> <chr>
#> 1 6 6 19FF0056789 FF
#> 2 6 7 19FF0056789 00
matches_not_found <- matches %>%
filter(is.na(map_id)) %>%
select(-map_id) %>%
inner_join(data, by = c("row_id" = "id"))
head(matches_not_found)
#> # A tibble: 1 x 2
#> row_id description
#> <int> <chr>
#> 1 7 19A0A123456
matches_found <- matches %>%
filter(!is.na(map_id)) %>%
inner_join(data, by = c("row_id" = "id")) %>%
inner_join(data_map, by = c("map_id" = "id"))
head(matches_found)
#> # A tibble: 6 x 4
#> row_id map_id description desc_map
#> <int> <int> <chr> <chr>
#> 1 1 2 19ABB123456 BB
#> 2 2 3 19BCC123456 CC
#> 3 3 4 19CDD123456 DD
#> 4 4 5 19DEE123456 EE
#> 5 5 6 19EFF456789 FF
#> 6 6 6 19FF0056789 FF
我的问题是,这段代码可以写成更tidy 功能性的方式吗?那会是什么样子?如果不能这样做,原因是什么?
【问题讨论】:
-
你能提供一些简单的示例数据来感受一下输入和输出吗?
-
您可以使用
reprex和datapasta包快速创建可重现的示例,以便其他人可以提供帮助。请不要使用str()、head()或截图。另见Help me Help you & How to make a great R reproducible example? -
从您的代码中不清楚
transactions[j, ]的来源。 -
如果你有足够的内存,简单地获取字符串的唯一向量(
data_map$desc_map)可能是合理的,将其作为data中的新列进行变异(放入list()) ,unnest,添加一个布尔列运行str_detectdata$description为每个,spread/pivot_wider和filter是必要的。如果你真的关心data_map中的 ID,你可以在任何时候left_join,假设 ID-desc_map 映射是唯一的,或者只使用 tibble 而不是具有初始变异的向量。 -
@TimTeaFan 我有时间根据 Tung 的反馈更新代码示例。
标签: r dplyr tidyverse stringr tibble