对于数据框中的每一行,查找另一个数据框中是否有 "close" 行
for each row in a data frame, find whether there is a "close" row in another data frame
我有以下数据框:
library(dplyr)
set.seed(42)
df <- data_frame(x = sample(seq(0, 1, 0.1), 5, replace = T), y = sample(seq(0, 1, 0.1), 5, replace = T), z= sample(seq(0, 1, 0.1), 5, replace = T) )
对于df
中的每一行,我想找出df2
中是否有一行在所有列中都接近它("neighbor"),其中"close"表示每列相差不超过0.1。
因此,例如,行 (1, 0.5, 0.5)
的适当邻居将是 (0.9, 0.6, 0.4)
。
第二组数据为
set.seed(42)
df2 <- data_frame(x = sample(seq(0, 1, 0.1), 10, replace = T), y = sample(seq(0, 1, 0.1), 10, replace = T), z= sample(seq(0, 1, 0.1), 10, replace = T) )
在这种情况下没有 "neighbor",所以我应该为 df
的所有行得到 "FALSE"。
我的实际数据框比这个大很多(几十列,几十万行,所以命名必须很笼统,而不是"x","y"和"z".
我觉得这可以使用 mutate
和 funs
来完成,例如我试过这一行:
df <- df %>% mutate_all(funs(close = (. <= df2(, .)+0.1) & (. >= df2(, .)-0.1))
但是出错了。
有什么想法吗?
您可以使用包 fuzzyjoin
library(fuzzyjoin)
# adding two rows that match
df2 <- rbind(df2,df[1:2,] +0.01)
df %>%
fuzzy_left_join(df2,match_fun= function(x,y) y<x+0.1 & y> x-0.1 ) %>%
mutate(found=!is.na(x.y)) %>%
select(-4:-6)
# # A tibble: 5 x 4
# x.x y.x z.x found
# <dbl> <dbl> <dbl> <lgl>
# 1 1 0.5 0.5 TRUE
# 2 1 0.8 0.7 TRUE
# 3 0.3 0.1 1 FALSE
# 4 0.9 0.7 0.2 FALSE
# 5 0.7 0.7 0.5 FALSE
在此处查找更多信息:Joining/matching data frames in R
这是一种在没有 fuzzyjoin
的情况下计算该列的方法
library(tidyverse)
found <-
expand.grid(row.df = seq(nrow(df)),
row.df2 = seq(nrow(df2))) %>%
mutate(in.range = pmap_lgl(., ~ all(abs(df[.x,] - df2[.y,]) <= 0.1))) %>%
group_by(row.df) %>%
summarise_at('in.range', any) %>%
select(in.range)
在多维数据集中查找 close 条目的机器学习方法是欧几里得距离。
一般的做法是规范化所有的属性。使每列的 运行ge 相同,零比一或负数一比一。这平衡了具有大值和小值的列的效果。当使用更高级的方法时,人们会将调整后的列值以零为中心。测试标准按比例缩放。
下一步是计算每个观测值与其邻居的距离。如果数据集很小或计算时间很短,计算每个观测值之间的距离。从 observation1 (row1) 到 observation2 (row2) 的欧几里得距离是 sqrt((X1 - X2)^2 + sqrt((Y1 - Y2)^2 + ...)。选择你的标准和 select.
在你的情况下,部分标准更简单。如果没有属性与另一个观察值相差超过 0.1,则两个观察值接近。我假设 df 和 df2 具有相同顺序的相同列数。我假设近距离观察相对较少。我的方法告诉我,一旦我们发现一对距离很远,就停止调查。如果您有数十万行,同时计算所有组合,您可能会耗尽内存。
~~~~~
你有一个大问题。如果您的数据集 df 和 df2 各有十万行和四打列,则机器需要进行 4.8e+11 次比较。最后的记分卡将有 1e+10 个结果(近距离或远距离)。我从一些子集开始与泪流满面的结果进行比较。 R 想要相同大小的矩阵。我设计的 kluge 没有成功。因此,我回到了 FORTRAN 的时代,并用循环来完成。使用循环方法,您可以将问题子集化并在不冒烟的情况下完成。
根据示例数据,我手动进行了比较,全部 150 个:nrow(df) * nrow(df2) * ncol(df)。根据您给出的定义,样本数据中没有密切观察。
这是我打算在 运行将结果提交到 df 中的新列之前呈现结果的方式。
dfclose <- matrix(TRUE, nrow = nrow(df), ncol = nrow(df2))
dfclose # Have a look
此矩阵描述了从 df 中的观察(dfclose 中的行)到 df2 中的观察(dfclose 中的列)的距离。如果关闭,则条目为 TRUE。
这里是距离测量结果的存储库:
dfdist <- matrix(0, nrow = nrow(df), ncol = nrow(df2))
dfdist # have a look; it's the same format, but with numbers
我们首先假设 df a 中的所有观测值都接近 df2。
总距离为零。为此,我们添加了曼哈顿距离。当曼哈顿总距离大于 0.1 时,它们不再靠近。不用再评价了。
closeCriterion <- function(origin, dest) {
manhattanDistance <- abs(origin-dest)
#print(paste("manhattanDistance =", manhattanDistance))
if (manhattanDistance < .1) ret <- 0 else ret <- 1
}
convertScore <- function(x) if (x>0) FALSE else TRUE
for (j in 1:ncol(df)) {
print(paste("col =",j))
for (i in 1:nrow(df)) {
print(paste("df row =",i))
for (k in 1:nrow(df2)) {
# print(paste("df2 row (and dflist column) =", k))
distantScore <- closeCriterion(df[i,j], df2[k,j])
#print(paste("df and dfdist row =", i, " df2 row (and dflist column) =", k, " distantScore = ", distantScore))
dfdist[i,k] <- dfdist[i,k] + distantScore
}
}
}
dfdist # have a look at the numerical results
dfclose <- matrix(lapply(dfdist, convertScore), ncol = nrow(df2))
我想看看这个过程在规模上会是什么样子。
set.seed(42)
df <- matrix(rnorm(3000), ncol = 30)
set.seed(42)
df2 <-matrix(rnorm(5580), ncol = 30)
dfdist <- matrix(0, nrow = nrow(df), ncol = nrow(df2))
然后我运行代码块看看会发生什么。
~~~
你可以考虑问题的定义。我 运行 模型好几次,改变了接近度的标准。如果 df2 中三打列的每一列中的条目都有 90% 的机会匹配其在 df 中的对应项,则该行只有 2.2% 的匹配机会。示例数据不是该算法的良好测试用例。
祝你好运
我有以下数据框:
library(dplyr)
set.seed(42)
df <- data_frame(x = sample(seq(0, 1, 0.1), 5, replace = T), y = sample(seq(0, 1, 0.1), 5, replace = T), z= sample(seq(0, 1, 0.1), 5, replace = T) )
对于df
中的每一行,我想找出df2
中是否有一行在所有列中都接近它("neighbor"),其中"close"表示每列相差不超过0.1。
因此,例如,行 (1, 0.5, 0.5)
的适当邻居将是 (0.9, 0.6, 0.4)
。
第二组数据为
set.seed(42)
df2 <- data_frame(x = sample(seq(0, 1, 0.1), 10, replace = T), y = sample(seq(0, 1, 0.1), 10, replace = T), z= sample(seq(0, 1, 0.1), 10, replace = T) )
在这种情况下没有 "neighbor",所以我应该为 df
的所有行得到 "FALSE"。
我的实际数据框比这个大很多(几十列,几十万行,所以命名必须很笼统,而不是"x","y"和"z".
我觉得这可以使用 mutate
和 funs
来完成,例如我试过这一行:
df <- df %>% mutate_all(funs(close = (. <= df2(, .)+0.1) & (. >= df2(, .)-0.1))
但是出错了。
有什么想法吗?
您可以使用包 fuzzyjoin
library(fuzzyjoin)
# adding two rows that match
df2 <- rbind(df2,df[1:2,] +0.01)
df %>%
fuzzy_left_join(df2,match_fun= function(x,y) y<x+0.1 & y> x-0.1 ) %>%
mutate(found=!is.na(x.y)) %>%
select(-4:-6)
# # A tibble: 5 x 4
# x.x y.x z.x found
# <dbl> <dbl> <dbl> <lgl>
# 1 1 0.5 0.5 TRUE
# 2 1 0.8 0.7 TRUE
# 3 0.3 0.1 1 FALSE
# 4 0.9 0.7 0.2 FALSE
# 5 0.7 0.7 0.5 FALSE
在此处查找更多信息:Joining/matching data frames in R
这是一种在没有 fuzzyjoin
library(tidyverse)
found <-
expand.grid(row.df = seq(nrow(df)),
row.df2 = seq(nrow(df2))) %>%
mutate(in.range = pmap_lgl(., ~ all(abs(df[.x,] - df2[.y,]) <= 0.1))) %>%
group_by(row.df) %>%
summarise_at('in.range', any) %>%
select(in.range)
在多维数据集中查找 close 条目的机器学习方法是欧几里得距离。
一般的做法是规范化所有的属性。使每列的 运行ge 相同,零比一或负数一比一。这平衡了具有大值和小值的列的效果。当使用更高级的方法时,人们会将调整后的列值以零为中心。测试标准按比例缩放。
下一步是计算每个观测值与其邻居的距离。如果数据集很小或计算时间很短,计算每个观测值之间的距离。从 observation1 (row1) 到 observation2 (row2) 的欧几里得距离是 sqrt((X1 - X2)^2 + sqrt((Y1 - Y2)^2 + ...)。选择你的标准和 select.
在你的情况下,部分标准更简单。如果没有属性与另一个观察值相差超过 0.1,则两个观察值接近。我假设 df 和 df2 具有相同顺序的相同列数。我假设近距离观察相对较少。我的方法告诉我,一旦我们发现一对距离很远,就停止调查。如果您有数十万行,同时计算所有组合,您可能会耗尽内存。
~~~~~
你有一个大问题。如果您的数据集 df 和 df2 各有十万行和四打列,则机器需要进行 4.8e+11 次比较。最后的记分卡将有 1e+10 个结果(近距离或远距离)。我从一些子集开始与泪流满面的结果进行比较。 R 想要相同大小的矩阵。我设计的 kluge 没有成功。因此,我回到了 FORTRAN 的时代,并用循环来完成。使用循环方法,您可以将问题子集化并在不冒烟的情况下完成。
根据示例数据,我手动进行了比较,全部 150 个:nrow(df) * nrow(df2) * ncol(df)。根据您给出的定义,样本数据中没有密切观察。
这是我打算在 运行将结果提交到 df 中的新列之前呈现结果的方式。
dfclose <- matrix(TRUE, nrow = nrow(df), ncol = nrow(df2))
dfclose # Have a look
此矩阵描述了从 df 中的观察(dfclose 中的行)到 df2 中的观察(dfclose 中的列)的距离。如果关闭,则条目为 TRUE。
这里是距离测量结果的存储库:
dfdist <- matrix(0, nrow = nrow(df), ncol = nrow(df2))
dfdist # have a look; it's the same format, but with numbers
我们首先假设 df a 中的所有观测值都接近 df2。 总距离为零。为此,我们添加了曼哈顿距离。当曼哈顿总距离大于 0.1 时,它们不再靠近。不用再评价了。
closeCriterion <- function(origin, dest) {
manhattanDistance <- abs(origin-dest)
#print(paste("manhattanDistance =", manhattanDistance))
if (manhattanDistance < .1) ret <- 0 else ret <- 1
}
convertScore <- function(x) if (x>0) FALSE else TRUE
for (j in 1:ncol(df)) {
print(paste("col =",j))
for (i in 1:nrow(df)) {
print(paste("df row =",i))
for (k in 1:nrow(df2)) {
# print(paste("df2 row (and dflist column) =", k))
distantScore <- closeCriterion(df[i,j], df2[k,j])
#print(paste("df and dfdist row =", i, " df2 row (and dflist column) =", k, " distantScore = ", distantScore))
dfdist[i,k] <- dfdist[i,k] + distantScore
}
}
}
dfdist # have a look at the numerical results
dfclose <- matrix(lapply(dfdist, convertScore), ncol = nrow(df2))
我想看看这个过程在规模上会是什么样子。
set.seed(42)
df <- matrix(rnorm(3000), ncol = 30)
set.seed(42)
df2 <-matrix(rnorm(5580), ncol = 30)
dfdist <- matrix(0, nrow = nrow(df), ncol = nrow(df2))
然后我运行代码块看看会发生什么。
~~~
你可以考虑问题的定义。我 运行 模型好几次,改变了接近度的标准。如果 df2 中三打列的每一列中的条目都有 90% 的机会匹配其在 df 中的对应项,则该行只有 2.2% 的匹配机会。示例数据不是该算法的良好测试用例。
祝你好运