【问题标题】:Group dataframes by columns and match by n elements按列对数据框进行分组并按 n 个元素匹配
【发布时间】:2019-03-22 22:33:48
【问题描述】:

所以这是我的问题。我有两个数据框。它们的简化版本如下。

df1
ID         String
1.1        a
1.1        a
1.1        b
1.1        c
...
1.2        a 
1.2        a
1.2        c
1.2        c
...
2.1        a
2.1        n
2.1        o
2.1        o
...
2.2        a
2.2        n
2.2        n
2.2        o
...
3.1        a
3.1        a
3.1        x
3.1        x
...
3.2        a
3.2        x
3.2        a
3.2        x
...
4.1        a
4.1        b
4.1        o
4.1        o
... 
4.2        a
4.2        b
4.2        b
4.2        o

假设每个 ID(例如:1.1)有超过 1000 行。另一件需要注意的事情是,在具有相同编号的 ID 的情况下(例如:1.1 和 1.2)非常相似。但彼此并不完全匹配。

df2
string2
a
b
a
c

df2 是一个测试 df。

我想看看哪个 df1 ID 与 df2 最接近。但我有一个非常重要的条件。我想匹配 n 个元素。不是针对另一个的整个数据框。

我的伪代码:

df2-elements-to-match <- df2$string2[1:n] #only the first n elements

group df1 by ID

df1-elements-to-match <- df1$String[1:n of every ID] #only the first n elements of each ID

Output a column with score of how many matches. 

Filter df1 to remove ID groups with < m score. #m here could be any number. 

Filtered df1 becomes new df1. 

n <- n+1 

df2-elements-to-match and df1-elements-to-match both slide down to the next n elements. Overlap is optional. (ex: if first was 1:2, then 3:4 or even 2:3 and then 3:4)

Reiterate loop with updated variables

If one ID remains stop loop.

这里的想法是在不必匹配整个测试数据帧的情况下获得预测匹配。

【问题讨论】:

  • 你能分享一个预期结果的例子吗?谢谢
  • 你能发布代码来为 df1 和 df2 创建一个最小版本吗?这样人们就可以玩弄它了吗?

标签: r string dataframe string-matching


【解决方案1】:
## minimal dfs
df1 <- data.frame(ID=c(rep(1.1, 5),
                       rep(1.2, 6),
                       rep(1.3, 3)),
                  str=unlist(strsplit("aabaaaabcababc", "")), stringsAsFactors=F)

df2 <- data.frame(str=c("a", "b", "a", "b"), stringsAsFactors=F)


## functions

distance <- function(df, query.df, df.col, query.df.col) {
  deviating <- df[, df.col] != query.df[, query.df.col]
    sum(deviating, na.rm=TRUE) # if too few rows, there will be NA, ignore NA
}

distances <- function(dfs, query.df, dfs.col, query.df.col) {
  sapply(dfs, function(df) distance(df, query.df, dfs.col, query.df.col))
}

orderedDistances <- function(dfs, query.df, dfs.col, query.df.col) {
  dists <- distances(dfs, query.df, dfs.col, query.df.col)
  sort(dists)
}

orderByDistance <- function(dfs, query.df, dfs.col, query.df.col, dfs.split.col) {
  dfs.split <- split(dfs, dfs[, dfs.split.col])
  dfs.split.N <- lapply(dfs.split, function(df) df[1:nrow(query.df), ])
  orderedDistances(dfs.split.N, query.df, dfs.col, query.df.col)
}


orderByDistance(df1, df2, "str", "str", "ID")
# 1.3 1.1 1.2 
#   1   3   3 

# 1.3 is the closest to df2!

您的问题有点像距离问题。 最小化距离 = 找到最相似的序列。

我在这里展示的这种距离假设在 df2 和 df1 的子 df 之间的等效位置,偏差被计为 1,相等被计为 0。总和给出了比较数据帧之间的unsimilarity-score - 字符串序列。

orderByDistance 接受dfs (df1) 和查询 df (df2),以及应该比较的列,以及应该拆分 dfs 的列(此处为“ID”)。 首先它拆分dfs,然后收集每个子df 的N 行(准备比较),然后在每个sub.df 上应用orderedDistances,确保N 行(N = 行数或行数)查询 df)。

【讨论】:

  • rderByDistance(FullHistory1_1, path1.1.1, "allPaths", "directions", "routeID") 关于上面的代码,path1.1.1 是我想检查的原始 querydf 的前 100 行的子集。我想要一个类似这样的解决方案:在得到上述结果后,过滤 dfs,以便只保留不相似性分数小于 50 的子 dfs,然后使用接下来的 100 行获取新的 querydf 子集并进行比较它与 dfs 依此类推,直到剩下一个子 df。每个 sub-df 的 N 行也应该对应于 querydf 的变化子集。
猜你喜欢
  • 2020-11-05
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
  • 2017-06-07
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多