【问题标题】:is.element() for more than one variableis.element() 用于多个变量
【发布时间】:2016-05-21 19:43:42
【问题描述】:

unique() 删除向量的重复元素和数组的重复行。

is.element()%in%match() 仅适用于向量(或 NULL)。

是否有多个变量的值匹配或设置操作?(例如数组的行)

我目前的解决方法是这样的。不是很优雅,显然对“_”匹配很敏感。

match.multiple <- function (x, table, nomatch = NA_integer_, incomparables = NULL) {
  x_vector <- apply(x, 1, paste, collapse="_")
  table_vector <- apply(table, 1, paste, collapse="_")
  match(x_vector, table_vector, nomatch, incomparables)}

is.element.multiple <- "%in.multiple%" <- function (el, set) match.multiple(el, set, 0) > 0

编辑:添加可重现的示例

假设您希望购买具有相同数量的前进档和化油器的汽车。可以是 1 辆、2 辆等。您不知道市场上可用的汽车(参见mtcars)是否符合您的偏好.

preferences <- cbind(1:8, 1:8)
available <- cbind(mtcars$gear, mtcars$carb)

所以你对两个变量进行匹配:齿轮化油器。

m <- match.multiple(preferences, available)
m
# [1] NA NA 12  1 NA NA NA NA
which(!is.na(m))
# [1] 3 4

这些是相同数量的前进档和化油器的数量。

willbuy <- m[!is.na(m)]
mtcars[willbuy, ]
#     mpg cyl  disp  hp drat   wt  qsec vs am gear carb
# 1: 16.4   8 275.8 180 3.07 4.07 17.40  0  0    3    3
# 2: 21.0   6 160.0 110 3.90 2.62 16.46  0  1    4    4

这些是您应该考虑的汽车目录条目。

【问题讨论】:

  • @dww 这不是一回事:它会在rbind(c("A", "B"), c("C", "D")) 中找到c("A", "C") 的匹配项
  • 好的,我误解了这个问题。以为您想在多个对象中找到一项。似乎您还想测试列表是否作为数组或列表列表中的子集出现。是否可以编辑问题以使其更明显?
  • @dww 我不想在我的问题中包含列表——它只会让它变得更复杂。但我确实想说清楚。 我希望将一个矩阵的行与另一个矩阵的行进行匹配。
  • 你的问题让我想起了 this question,我在 10 个月前用一个疯狂的 Rcpp 解决方案回答了这个问题。只是一种可能。
  • 具有所需输出的可重现示例将很有帮助stackoverflow.com/questions/5963269/…

标签: r


【解决方案1】:

正如我在 cmets 中提到的,我对this question 的回答可以适应这个问题。以下是如何完成它,并通过 OP 的可重现示例进行演示:

avail <- cbind(mtcars$gear,mtcars$carb);
prefs <- cbind(1:8,1:8);
do.call(rbind,apply(prefs,1L,function(x) mtcars[findarray(avail,matrix(x,1L))[,1L],]));
##                mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Merc 450SE    16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL    17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC   15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Mazda RX4     21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Merc 280      19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C     17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4

【讨论】:

  • 尽管我付出了所有努力,但还是无法正确安装 Rtools。但是,如果我们将代码中的findarray(avail,matrix(x,1L))[,1L] 更改为apply(avail, 1, all.equal, x) == TRUE,它会给出相同的结果——不需要gcc。我确实知道您的 n 维子矩阵查找器是一个功能更强大的工具,我只是看不出我们如何在这里利用它的优势。
  • 这应该比@dww 的解决方案更快,因为它是用 C++ 编写的。但它并不容易使用,因为拥有一个有效的 Rtools 有多种复杂性。 #bitterexperience
【解决方案2】:

在数组的行中查找向量出现的函数:

为了测试一个向量 (v) 是数组的一行还是矩阵 (m),我们可以构造第二个矩阵,其维度与我们要搜索的那个相同,但由我们重复的向量行组成正在寻找,并检查此构造数组中的任何行是否与原始数组相同

is.row.in.rows <- function(v,m) {
  which(length(v) == rowSums(m == matrix(v, nrow(m), ncol(m), byrow=TRUE)))
}

请注意,也可以使用which(apply(m, 1, all.equal, v) == TRUE) 循环执行相同的测试。但是,上面使用 rowSums 的矢量化版本更快。

使用此函数解决问题中的可重现示例:

a <- unlist(apply(preferences, MARGIN = 1, is.row.in.rows, available))
a
# [1] 12 13 14  1  2 10 11

mtcars[a,]
#               mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Merc 450SE    16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
# Merc 450SL    17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
# Merc 450SLC   15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
# Mazda RX4     21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# Merc 280      19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
# Merc 280C     17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4

【讨论】:

  • is.row.in.rows 函数在比较不同大小的数组时会抛出错误(就像在前面的示例中一样):m &lt;- matrix(1:25, 5); v &lt;- rep(1, 6); is.row.in.rows(v, m) 你应该试试这个:any(apply(m, 1, identical, v))——这对类差异很敏感.或者这个:any(apply(m, 1, all.equal, v) == TRUE)——不是。
  • 我没有注意到您更改了函数的代码。我的上述评论在没有which 的情况下成立。当前版本的is.row.in.rows 应与which(apply(m, 1, all.equal, v) == TRUE) 进行比较。
  • 是的,这很相似,但并不完全相同。 all.equal 测试对象是否几乎相同,而不是相同。而且我认为 rowSums 可能比 apply(all.equal) 更快
  • 确实更快。
  • 为了使其更快,您可以使用byrow=TRUE 放弃转置。例如:which(length(v) == rowSums(m == matrix(v, nrow(m), ncol(m), byrow=TRUE)))
猜你喜欢
  • 2016-11-14
  • 2011-12-09
  • 2015-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
相关资源
最近更新 更多