我有一个包含字符串和ID行的数据框。我称之为历史。
history
ID string
1.1 a b b b c c s d s ....
1.2 a b b b b c s s d ....
2.1 a c c s s d b d b ....
2.2 a c s c s d b d b ....
3.1 a z z x d b d d f ....
3.2 a z x z d d f b d ....
...
每行中的字符串都很长。属于相同编号(如1.1和1.2)的ID具有相似的字符串,但有细微差别。虽然1.1和2.2之间会有较大的差异。原始数据中大约有70行。
test
string
a c c c s s d b d b....
我的目标是,如果我有另一个包含“历史记录”中不存在的字符串的数据框,我想在“历史记录”中找到最匹配的ID。我知道有很多文本匹配方法可以做到这一点。我的问题来自以下事实:我无法将“测试”中的整个字符串与“历史记录”进行匹配。
整个过程的重点是看我是否可以找出“ test”中的字符串属于哪个ID,而不必匹配整个字符串。我想到的一个想法是在测试中进行更多匹配时过滤掉历史记录。
我的预期输出: 在这里,我假设匹配以“ test”中字符串的第一个字符开始,而不是“ history”中字符串的第一个字符开始。而且我们一个一个地走。这两个假设都不是固定的。同样,“历史”和“测试”中字符串的长度也可以不同。
“ test”中的第一个字符“ a”与“ history”中的所有人匹配。因此,在这种情况下不会进行过滤。
test
string
a
结果:
history
ID string
1.1 a b b b c c s d s ....
1.2 a b b b b c s s d ....
2.1 a c c s s d b d b ....
2.2 a c s c s d b d b ....
3.1 a z z x d b d d f ....
3.2 a z x z d d f b d ....
...
第二个字符是“ c”。这里要确保我们没有匹配“历史”中某个地方的随机“ c”,我认为建立规则会有所帮助。如果是“ a”然后是“ c”,则会出现类似匹配的情况。
test
string
a c
结果:
history
ID string
2.1 a c c s s d b d b ....
2.2 a c s c s d b d b ....
这已将匹配范围缩小到历史记录ID 2.1和2.2。坦白说,我们甚至可以像我之前所说的那样在这儿停下来。因此,总之,一旦将历史记录过滤为一个ID,就应该输出与“测试”字符串最匹配的ID。
答案 0 :(得分:1)
这里有两个tidyverse
解决方案,它们将返回ID
值,该值具有与测试字符串最大匹配数和最大匹配数:
df = data.frame(ID = c(1.1,1.2,2.1,2.2,3.1,3.2),
string = c("a b b b c c s d s",
"a b b b b c s s d",
"a c c s s d b d b",
"a c s c s d b d b",
"a z z x d b d d f",
"a z x z d d f b d"),
stringsAsFactors = F)
library(tidyverse)
# string to test
test = "a c c c s s"
选项1 (考虑任意位置的匹配项)
df %>%
separate_rows(string) %>%
group_by(ID) %>%
mutate(test = unlist(strsplit(test, split = " "))[row_number()]) %>%
na.omit() %>%
summarise(matches = sum(string == test)) %>%
filter(matches == max(matches))
# # A tibble: 2 x 2
# ID matches
# <dbl> <int>
# 1 2.1 4
# 2 2.2 4
选项2 (考虑连续的比赛)
df %>%
separate_rows(string) %>%
group_by(ID) %>%
mutate(test = unlist(strsplit(test, split = " "))[row_number()]) %>%
na.omit() %>%
summarise(matches = sum(cumprod(string == test))) %>%
filter(matches == max(matches))
# # A tibble: 1 x 2
# ID matches
# <dbl> <dbl>
# 1 2.1 3
答案 1 :(得分:0)
以AntoniosK上面给出的出色示例为基础:
您可以为每列应用一些加权因子。因此,如果第1列非常重要,则将其乘以10.000,将第二列仅乘以1.000。然后将这些值逐行求和,找到最高的总和以获得最合适的字符串。
(又是a b c d e f比a b c d e f匹配得更好)
library(tidyverse)
df = data.frame(ID = c(1.1,1.2,2.1,2.2,3.1,3.2),
string = c("a b b b c c s d s",
"a b b b b c s s d",
"a c c s s d b d b",
"a c s c s d b d b",
"a z z x d b d d f",
"a z x z d d f b d"),
stringsAsFactors = F)
# string to test
test <- "a c c c s s"
weights <- c(1000,100,10,10,10,10,10,10,10)
df_answer <- df %>%
separate_rows(string) %>%
group_by(ID) %>%
mutate(test = unlist(strsplit(test, split = " "))[row_number()]) %>%
mutate(scores = (string == test) * weights) %>%
summarise(scores = sum(scores, na.rm = TRUE)) %>%
filter(scores == max(scores))
# A tibble: 2 x 2
# ID scores
# <dbl> <dbl>
#1 2.1 1120
#2 2.2 1120