基于R中的多个列值创建值序列

基于R中的多个列值创建值序列,r,dplyr,data.table,R,Dplyr,Data.table,我有一个data.frame,它是点的近邻搜索的结果,它有三列:V1表示最近点的索引,V2表示第二个最近点,V3表示第三个最近点: search_result <- structure(list(V1 = c(1350L, 1390L, 1411L, 1437L, 1444L, 1895L, 1895L, 1467L, 1478L, 1500L),

我有一个data.frame,它是点的近邻搜索的结果,它有三列:V1表示最近点的索引,V2表示第二个最近点,V3表示第三个最近点:

search_result <- structure(list(V1 = c(1350L, 1390L, 1411L, 1437L, 1444L, 1895L, 
                                       1895L, 1467L, 1478L, 1500L), 
                                V2 = c(1351L, 1391L, 1410L, 1438L, 
                                       1907L, 1456L, 1456L, 1466L, 1477L, 1499L), 
                                V3 = c(1349L, 1389L, 1940L, 1913L, 1445L, 1894L, 
                                       1894L, 1884L, 1479L, 1501L)), 
                           row.names = c(NA, -10L), 
                           class = "data.frame")
我试图取每列的最小值,但在数据集的后面有一些情况下,最大值是所需的(不是最佳选项,但更接近预期值)。在下面的示例中,第2、4、5和6行存在不连续性,因此我将采用V2(优先级)或V3作为所需的值,因此“顺序”保持不变:

# it's harder to see the "order" here, but it starts in V1 = 1881

   V1   V2   V3  ordered
1 1881 1470 1880    1881
2 1457 1893 1894    1893 #take V2 instead
3 1907 1444 1906    1907
4 1442 1443 1908    1908 #take V3 instead
5 1433 1918 1432    1918 #take V2 instead
6 1402 1949 1401    1949 #take V2 instead
7 1968 1969 1967    1968
8 1985 1986 1984    1985
9 1992 1993 1991    1992
整个数据集有2500个点,“无序”值发生在大约10%的数据集中,因此我可以估计“顺序”是什么


任何
base
tidyverse
数据。如有任何
表格
帮助,将不胜感激。谢谢

听起来您想要做的是迭代搜索返回的每一列,并在每一行的前面,保持满足索引的第一个值是有序的

首先假设第一列是有序的。移动到第二列并替换不符合此条件的所有行。移动到第三列,与更新的有序列进行比较。对所有列继续

可能有一种更优化的编码方法(例如在迭代所有列之前检查答案是否收敛),但这里有一种简洁的方法来实现这一点(注意
lag
函数是
dplyr::lag
而不是
stats::lag
):

库(dplyr)
图书馆(purrr)
#使用第二个数据集
#假设至少有一列满足约束条件
数据帧(
V1=c(18811145719071442143314021688198519851992),
V2=c(147018931444431918194919698619861993),
V3=c(188018941906190814321440196719841991)
) %>%
dplyr::突变(
有序=减少(,~ifelse(.x>=lag(.x,默认值=0),.x,.y))
)
#>已订购V1 V2 V3
#> 1 1881 1470 1880    1881
#> 2 1457 1893 1894    1893
#> 3 1907 1444 1906    1907
#> 4 1442 1443 1908    1908
#> 5 1433 1918 1432    1918
#> 6 1402 1949 1401    1949
#> 7 1968 1969 1967    1968
#> 8 1985 1986 1984    1985
#> 9 1992 1993 1991    1992
如果您不确定从最近邻搜索返回的列是否足够多,则必须再添加一次迭代,以检查有序列是否升序

搜索结果%
dplyr::突变(
有序=减少(,~ifelse(.x>=lag(.x,默认值=0),.x,.y))
)
使用(搜索结果,任意(有序<滞后(有序,默认值=0)))
#>[1]是的

由(v0.3.0)

于2019-07-19创建,由于
V1
应始终增加,我们可以将
V1
的第一个值作为参考,并用该
第一个值减去第二行的所有值,然后取差异最小的值。因为,我们还想考虑一种方法,就是用增量数乘以差值。在这个例子中,我刚刚将它乘以整数1、2和3。第一个差乘以1,第二个差乘以2,依此类推。如果发现一些边缘情况,可以考虑使用更复杂的方法来分配优先级

first_value <- search_result$V1[1]
search_result$ordered <- c(first_value, apply(search_result[-1, ], 1, function(x) {
     x <- x[x > first_value]
     x[which.min((x - first_value) * seq_along(x))]
}))

search_result
#     V1   V2   V3 ordered
#1  1350 1351 1349    1350
#2  1390 1391 1389    1390
#3  1411 1410 1940    1411
#4  1437 1438 1913    1437
#5  1444 1907 1445    1444
#6  1895 1456 1894    1456
#7  1895 1456 1894    1456
#8  1467 1466 1884    1467
#9  1478 1477 1479    1478
#10 1500 1499 1501    1500

只取最小的列就足够了吗?这似乎适合您的示例数据,但我不知道这是否会更普遍地起作用。如果没有,是否有一种一致的数学方法来确定哪些行“无序”?我添加了一些最小值不够的情况。我可以识别(使用
diff
)可能存在不连续的地方,但它也会将一些“ok”值识别为可疑值,特别是当存在从坏值到ok值的转换时。在某些情况下,似乎可能存在多个可能的解决方案,例如,V2值不能在第8+9行中使用,并且仍然是“有序”的吗?如果一行中有V2,另一行中有V3,或者V3和V2——哪种匹配更好?如果在某一点上,
V1:V3
都不大于或等于前一行的
ordered
值,会发生什么情况?在第一个示例中,第6行,如果
1895>1444
(即订单仍在增加),您为什么要选择
V2
?谢谢
减少
!但在第一个示例中,它不起作用。首先,在第5-6行中有一个明显的“不连续”,但它仍然是有序的。所以我想我可以设置一个阈值(比如100)来确定是否存在不连续:
ordered=reduce(,~ifelse(abs(.x-lag(.x,default=0))你能澄清一下你选择有序列的值的逻辑吗?从你上面的评论来看是不是1)值必须按升序排列2)第一个值不是不连续的(由阈值确定)?第二个点意味着所选值不必与前一个值绝对最接近,仅在阈值范围内。也就是说,这就是为什么对于第二个数据集,选择第三行1907而不是1906(尽管后者更接近1893)
first_value <- search_result$V1[1]
search_result$ordered <- c(first_value, apply(search_result[-1, ], 1, function(x) {
     x <- x[x > first_value]
     x[which.min((x - first_value) * seq_along(x))]
}))

search_result
#     V1   V2   V3 ordered
#1  1350 1351 1349    1350
#2  1390 1391 1389    1390
#3  1411 1410 1940    1411
#4  1437 1438 1913    1437
#5  1444 1907 1445    1444
#6  1895 1456 1894    1456
#7  1895 1456 1894    1456
#8  1467 1466 1884    1467
#9  1478 1477 1479    1478
#10 1500 1499 1501    1500
first_value <- df$V1[1]
df$ordered <- c(first_value, apply(df[-1, ], 1, function(x) {
     x <- x[x > first_value]
     x[which.min((x - first_value) * seq_along(x))]
}))

df
#    V1   V2   V3 ordered
#1 1881 1470 1880    1881
#2 1457 1893 1894    1893
#3 1907 1444 1906    1907
#4 1442 1443 1908    1908
#5 1433 1918 1432    1918
#6 1402 1949 1401    1949
#7 1968 1969 1967    1968
#8 1985 1986 1984    1985
#9 1992 1993 1991    1992