首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据该数据帧中的多个匹配准则和另一个数据帧B,获得数据帧A的行索引

根据该数据帧中的多个匹配准则和另一个数据帧B,获得数据帧A的行索引
EN

Stack Overflow用户
提问于 2016-11-10 12:32:28
回答 1查看 76关注 0票数 2

假设我们在R、df.Adf.B中有两个数据帧,定义如下:

代码语言:javascript
复制
bin_name <- c('bin_1','bin_2','bin_3','bin_4','bin_5')
bin_min <- c(0,2,4,6,8)
bin_max <- c(2,4,6,8,10)
df.A <- data.frame(bin_name, bin_min, bin_max, stringsAsFactors = FALSE)

obs_ID <- c('obs_1','obs_2','obs_3','obs_4','obs_5','obs_6','obs_7','obs_8','obs_9','obs_10')
obs_min <- c(6.5,0,8,2,1,7,5,6,8,3)
obs_max <- c(7,3,10,3,9,8,5.5,8,10,4)
df.B <- data.frame(obs_ID, obs_min, obs_max, stringsAsFactors = FALSE)

df.A定义了回收箱的范围,而df.B则由带有min和max值的行组成,这些观察值可能或不完全属于df.A中定义的bin。

我们希望生成一个长度为nrow(df.B)的新向量,该向量包含df.A的行索引,该索引对应于每个观察完全落在其中的bin。如果一个观察横跨一个垃圾桶,或者部分地掉在它外面,那么它就不能分配给一个bin,而应该返回NA (或类似的东西)。

在上面的例子中,正确的输出向量是:

代码语言:javascript
复制
bin_rows <- c(4, NA, 5, 2, NA, 4, 3, 4, 5, 2)

我想出了一个使用sapply的冗长的解决方案。

代码语言:javascript
复制
bin_assignments <- sapply(1:nrow(df.B), function(i) which(df.A$bin_max >= df.B$obs_max[i] & df.A$bin_min <= df.B$obs_min[i])) #get bin assignments for every observation
bin_assignments[bin_assignments == "integer(0)"] <- NA #replace "integer(0)" entries with NA
bin_assignments <- do.call("c", bin_assignments) #concatenate the output of the sapply call

几个月前,我发现了一个解决这个问题的简单的单行解决方案,它没有使用应用函数。然而,我忘记了我是如何做到这一点的,而且我也无法重新发现它!解决方案可能涉及match()which()。有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-10 13:06:15

1)使用可以很容易地在一条语句中完成:

代码语言:javascript
复制
library(sqldf)

sqldf('select a.rowid
       from "df.B" b 
       left join "df.A" a on obs_min >= bin_min and obs_max <= bin_max')

   rowid
1      4
2     NA
3      5
4      2
5     NA
6      4
7      3
8      4
9      5
10     2

2) merge/by,我们可以使用mergeby在两个语句中进行合并。不使用包装。

这确实有一个缺点,即它实现了SQL解决方案不需要做的大型联接。

注意,问题中定义的df.Bobs_10是第二级而不是第10层。如果是这样的话,obs_10是第10层,那么by的第二个参数可能就是m$obs_ID,所以首先修复输入可以简化它。

代码语言:javascript
复制
m <- merge(df.B, df.A)
stack(by(m, as.numeric(sub(".*_", "", m$obs_ID)), 
      with, c(which(obs_min >= bin_min & obs_max <= bin_max), NA)[1]))

给予:

代码语言:javascript
复制
   values ind
1       4   1
2      NA   2
3       5   3
4       2   4
5      NA   5
6       4   6
7       3   7
8       4   8
9       5   9
10      2  10

3)

代码语言:javascript
复制
sapply(1:nrow(df.B), function(i)
  c(which(df.A$bin_max >= df.B$obs_max[i] & df.A$bin_min <= df.B$obs_min[i]), NA)[1]) 

给予:

代码语言:javascript
复制
[1]  4 NA  5  2 NA  4  3  4  5  2

3a) -- @Ronak‘在评论中给出了更好的(3)使用mapply的变体:

代码语言:javascript
复制
mapply(function(x, y) c(which(x >= df.A$bin_min & y <= df.A$bin_max), NA)[1], 
       df.B$obs_min, 
       df.B$obs_max)

4)外部是另一个不使用包的语句解决方案。

代码语言:javascript
复制
seq_len(nrow(df.A)) %*% 
  (outer(df.A$bin_max, df.B$obs_max, ">=") & outer(df.A$bin_min, df.B$obs_min, "<="))

给予:

代码语言:javascript
复制
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    4    0    5    2    0    4    3    4    5     2
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40527724

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档