基于具有“容差”的数值向量过滤数据框

Posted

技术标签:

【中文标题】基于具有“容差”的数值向量过滤数据框【英文标题】:Filter data frame based on numeric vector with "tolerance" 【发布时间】:2022-01-22 16:41:54 【问题描述】:

我想使用数字向量过滤数据框。我正在应用以下功能:

test_data <- exp_data[exp_data$Size_Change %in% vec_data,]

示例数据如下所示:

dput(exp_data)
structure(list(Name = c("Mark", "Greg", "Tomas", "Morka", "Pekka", 
"Robert", "Tim", "Tom", "Bobby", "Terka"), Mode = c(1, 2, NA, 
4, NA, 3, NA, 1, NA, 3), Change = structure(c(6L, 2L, 4L, 5L, 
7L, 7L, 7L, 8L, 3L, 1L), .Label = c("D[+58], I[+12][+385]", "C[+58], K[+1206]", 
"C[+58], P[+2074]", "C[+58], K[+2172]", "C[+58], K[+259]", "C[+58], K[+2665]", 
"C[+58], T[+385]", "C[+58], C[+600]"), class = "factor"), Size = c(1335.261, 
697.356, 1251.603, 920.43, 492.236, 393.991, 492.239, 727.696, 
1218.933, 495.237), Place = c(3L, 4L, 3L, 2L, 4L, 5L, 4L, 3L, 
3L, 4L), Size_Change = c(4004, 2786, 3753, 1840, 1966, 1966, 
1966, 2181, 3655, 1978)), row.names = 2049:2058, class = "data.frame")

和用于过滤的向量:

dput(vec_data)
c(4003, 2785, 954, 1129, 4013, 756, 1852, 2424, 1954, 246, 147, 
234, 562, 1617, 2180, 888, 1176)

我提到了容差,因为vec_data 不是很精确,我期望数字有 +1/-1 的差异,并且在应用函数后它不会过滤具有这种差异的行。也可能会出现 +12/-12 或 +24/-24 的差异。我可以在过滤时以某种方式考虑它吗?

当然,可能的解决方案是像 (vec_data +1) / (vec_data -1) / (vec_data +12) 等那样做一些过滤尝试,最后可能是所有的 rbind 输出,但我正在寻找更“优雅”的方式。如果可以添加一个列来指示该行是如何过滤的,如果它是来自vec_data 的确切数字或者它被+1、+12、-24 或其他修改,那也很棒。请注意,+1/-1 与任何其他修改的组合也是可能的。如果它太复杂,则不需要额外的列。

【问题讨论】:

如果你得到Error: unexpected token,你可能使用的是R版本update your R。 【参考方案1】:

一个选项可能是(容差 = 1):

df %>%
    filter(sapply(Size_Change, function(x) any(abs(x - vec) %in% 0:1)))

  Name Mode           Change     Size Place Size_Change
1 Mark    1 C[+58], K[+2665] 1335.261     3        4004
2 Greg    2 C[+58], K[+1206]  697.356     4        2786
3  Tom    1  C[+58], C[+600]  727.696     3        2181

公差 = 14:

df %>%
    filter(sapply(Size_Change, function(x) any(abs(x - vec) %in% 0:14)))

    Name Mode           Change     Size Place Size_Change
1   Mark    1 C[+58], K[+2665] 1335.261     3        4004
2   Greg    2 C[+58], K[+1206]  697.356     4        2786
3  Morka    4  C[+58], K[+259]  920.430     2        1840
4  Pekka   NA  C[+58], T[+385]  492.236     4        1966
5 Robert    3  C[+58], T[+385]  393.991     5        1966
6    Tim   NA  C[+58], T[+385]  492.239     4        1966
7    Tom    1  C[+58], C[+600]  727.696     3        2181

rowwise()的逻辑相同:

df %>%
    rowwise() %>%
    filter(any(abs(Size_Change - vec) %in% 0:1))

【讨论】:

是否也允许容忍-1 它使用绝对差异,所以 +1 和 -1 :)【参考方案2】:

最明显的方法是根据不等式而不是精确匹配进行过滤(在比较数字 [非整数] 时始终推荐)

comp <- function(x, yvec, tolerance = 1)
  sapply(x, \(xi)any(abs(xi - yvec) <= tolerance))

exp_data[comp(exp_data$Size_Change, vec_data),]
     Name Mode           Change     Size Place Size_Change
2049 Mark    1 C[+58], K[+2665] 1335.261     3        4004
2050 Greg    2 C[+58], K[+1206]  697.356     4        2786
2056  Tom    1  C[+58], C[+600]  727.696     3        2181
# Tolerance = 2
# exp_data[comp(exp_data$Size_Change, vec_data, 2),]

【讨论】:

我的 RStudio 将斜杠识别为意外标记。不知道,但似乎斜线不能在我的 R..中使用。 啊,\(x)... 表示法是在 R-4.1.0 中实现的。如果您使用的是之前的版本,则需要使用 function(x) 而不是 \(x) 好吧,明白了。谢谢。【参考方案3】:

使用tolerance 函数怎么样?

tol <- \(x, tol=1L) sapply(seq(-tol, tol, 1L), \(i) sweep(as.matrix(x), 1L, i))

exp_data[exp_data$Size_Change %in% tol(vec_data), ]

#      Name Mode           Change     Size Place Size_Change
# 2049 Mark    1 C[+58], K[+2665] 1335.261     3        4004
# 2050 Greg    2 C[+58], K[+1206]  697.356     4        2786
# 2056  Tom    1  C[+58], C[+600]  727.696     3        2181

它默认为公差±1,如果我们想要±24,我们可以在参数中定义它:

exp_data[exp_data$Size_Change %in% tol(vec_data, 24L), ]
#        Name Mode               Change     Size Place Size_Change
# 2049   Mark    1     C[+58], K[+2665] 1335.261     3        4004
# 2050   Greg    2     C[+58], K[+1206]  697.356     4        2786
# 2052  Morka    4      C[+58], K[+259]  920.430     2        1840
# 2053  Pekka   NA      C[+58], T[+385]  492.236     4        1966
# 2054 Robert    3      C[+58], T[+385]  393.991     5        1966
# 2055    Tim   NA      C[+58], T[+385]  492.239     4        1966
# 2056    Tom    1      C[+58], C[+600]  727.696     3        2181
# 2058  Terka    3 D[+58], I[+12][+385]  495.237     4        1978

我想知道24L 中的L,它是整数表示法,你也可以使用tol=24 没有任何问题。

注意: R 版本 4.1.2 (2021-11-01)

【讨论】:

以上是关于基于具有“容差”的数值向量过滤数据框的主要内容,如果未能解决你的问题,请参考以下文章

在向量上过滤数据框[重复]

07_LFM--梯度下降法--实现基于模型的协同过滤

过滤数据框中的值

如何过滤表单中具有多个组合框的 Access 子表单?

过滤熊猫数据框列中的字符串/浮点数/整数值

使用带有数值的组合框访问过滤器表单