字符串匹配两个带有滑动窗口的数据框

时间:2018-08-16 06:22:24

标签: r dataframe dplyr sliding-window

我有两个df。

df1
       col1
    1    a
    2    b
    3    c
    4    c
df2
   setID col1
1      1    a
2      1    b
3      1    b
4      1    a
5      2    w
6      2    v
7      2    c
8      2    b
9      3    a
10     3    a
11     3    b
12     3    a
13     4    a
14     4    b
15     4    c
16     4    a

我正在使用以下代码来匹配它们。

scorematch <- function () 
{
      require("dplyr")
      #to make sure every element is preceded by the one before that element
      combm <- rev(sapply(rev(seq_along(df1$col1)), function(i) paste0(df1$col1[i-1], df1$col1[i])));
      tempdf <- df2
      #group the history by their ID
      tempdf <- group_by(tempdf, setID)
      #collapse strings in history
      tempdf <- summarise(tempdf, ss = paste(col1, collapse = ""))
      tempdf <- rowwise(tempdf)
      #add score based on how it matches compared to path
      tempdf <- mutate(tempdf, score = sum(sapply(combm, function(x) sum(grepl(x, ss)))))
      tempdf <- ungroup(tempdf)
      #filter so that only IDs with scores more than 0 are available
      tempdf <- filter(tempdf, score != 0)
      tempdf <- pull(tempdf, setID)
      #filter original history to reflect new history
      tempdf2 <- filter(df2, setID %in% tempdf)
      tempdf2
    }

此代码效果很好。但我想更进一步。我想应用滑动窗口函数来获取要与df2匹配的df1值。到目前为止,我将此功能用作滑动窗口。

slidingwindow <- function(data, window, step)
{
  #data is dataframe with colname
  total <- length(data)
  #spots are start of each window
  spots <- seq(from=1, to=(total-step), by=step)
  result <- vector(length = length(spots))
  for(i in 1:length(spots)){
    ...
  }
  return(result)
}

scorematch函数将嵌套在滑动窗口函数中。我不确定如何从那里继续。理想情况下,df1将被拆分为多个窗口。从第一个窗口开始,将使用scorematch函数将其与df2进行匹配,以获取过滤出的df2。然后,我希望df1的第二个窗口与新过滤的df2相匹配,依此类推。过滤完df2后,循环应结束,以便仅包含1个不同的setID值。最终输出可以是整个已过滤的df2,也可以只是其余的setID。 理想的输出将是

  setID col1
1     4    a
2     4    b
3     4    c
4     4    a

[1] "4"

1 个答案:

答案 0 :(得分:1)

这是不使用for循环的解决方案。我使用stringr是因为它的语法一致,purrr的{​​{1}}(尽管在这种情况下,map就足够了),lapply到{{1} } setID并折叠每个组的字符串。

dplyr

首先,我折叠每个组的字符串。这样可以更轻松地将模式匹配与group_by之后一起使用:

library(dplyr)
library(purrr)
library(stringr)

“查找”字符串也将折叠,然后用str_detect提取子字符串(即滑动窗口)。在这里,我沿着字符串df2_collapse <- df2 %>% group_by(setID) %>% summarise(string = str_c(col1, collapse = "")) df2_collapse # A tibble: 4 x 2 # setID string # <int> <chr> # 1 1 abba # 2 2 wvcb # 3 3 aaba # 4 4 abca 的长度进行工作,并提取字符串中每个字母后面的所有可能的组。

str_sub

将子字符串以其长度作为分数的小节形式存储。

str_length

对于每个提取了其最大分数的setID,它会在子字符串数据中进行匹配,并过滤掉具有所有setID的最大分数的行。

string <- str_c(df1$col1, collapse = "")

string
# [1] "abcc"

substrings <- 
  unlist(map(1:str_length(string), ~ str_sub(string, start = .x, end = .x:str_length(string))))

数据

substrings
# [1] "a"    "ab"   "abc"  "abcc" "b"    "bc"   "bcc"  "c"    "cc"   "c" 

substrings <- tibble(substring = substrings, 
                     score = str_length(substrings))

substrings
# A tibble: 10 x 2
#    substring score
#    <chr>     <int>
#  1 a             1
#  2 ab            2
#  3 abc           3
#  4 abcc          4
#  5 b             1
#  6 bc            2
#  7 bcc           3
#  8 c             1
#  9 cc            2
# 10 c             1