我有以下数据框:
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
中是否在所有列中都靠近该行(“邻居”),其中“ 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) )
在这种情况下,没有“邻居”,因此Im应该对df
的所有行都获得“ FALSE”。
我的实际数据帧要比这大得多(数十列和数十万行,因此命名必须非常笼统,而不是“ x”,“ y”和“ z”。
我认为可以使用mutate
和funs
来完成此操作,例如,我尝试了以下这一行:
df <- df %>% mutate_all(funs(close = (. <= df2(, .)+0.1) & (. >= df2(, .)-0.1))
但是出现错误。
有什么想法吗?
答案 0 :(得分:2)
您可以使用软件包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
答案 1 :(得分:0)
在多维数据集中查找 close 条目的机器学习方法是欧几里得距离。
一般方法是规范所有属性。使每列的范围相同,零到一或负一比一。这样就可以均衡具有大和小值的列的效果。如果使用更高级的方法,则将调整后的列值居中于零。测试标准按相同比例缩放。
下一步是计算每个观察点到其邻近点的距离。如果数据集很小或计算时间很便宜,请计算每个观测值到彼此的距离。从观测值1(行1)到观测值2(行2)的欧几里得距离是sqrt((X1-X2)^ 2 + sqrt((Y1-Y2)^ 2 + ...)。选择您的条件并选择。
在您的情况下,截面标准更简单。如果没有一个属性比另一个观察值大,则两个观察值接近。我假设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。 总距离为零。为此,我们加上曼哈顿距离。当曼哈顿总距离大于.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%的机会与之匹配。示例数据对于该算法而言并不是一个很好的测试案例。
祝你好运
答案 2 :(得分:-1)
这是不使用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)