Группировать кадры данных по столбцам и сопоставлять по n элементам - PullRequest
0 голосов
/ 18 октября 2018

Так вот моя проблема.У меня есть два кадра данных.Упрощенная версия их ниже.

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

Представьте, что каждый идентификатор (например, 1.1) содержит более 1000 строк.Следует также отметить, что идентификаторы с одинаковым номером (например, 1.1 и 1.2) очень похожи.Но не точное совпадение друг с другом.

df2
string2
a
b
a
c

df2 - это тестовый df.

Я хочу посмотреть, какой из идентификаторов df1 наиболее близко соответствует 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.

Идея в том, чтобы получить предсказанное совпадение, не сопоставляя весь тестовый фрейм данных.

1 Ответ

0 голосов
/ 18 октября 2018
## 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 и sub-df в df1 отклонения учитываются как 1, а равенство - как 0.Сумма дает unsimilarity-score между сравниваемыми фреймами данных - последовательностями строк.

orderByDistance занимает dfs (df1) и запрос df (df2), а также столбцы, которые должны сравниваться, истолбец, по которому следует разделить dfs (здесь «ID»).Сначала он разбивает dfs, затем он собирает N строк каждого подпрограммы (подготовка к сравнению), а затем применяет orderedDistances к каждому подпапке с гарантированными N строками (N = число или строкизапрос df).

...