2015-11-06 44 views
-2

编辑 我离开的情况下,它是有用的人的问题,但现在看来,这竟是dplyr版中的问题[见下文] 。dplyr ::从另一个数据帧上的不同列多个条件变异


R和使用dplyr,我有两个数据帧df1df2

library(dplyr) 
set.seed(2) 
df1 = data.frame(letter=rep(letters[1:2], each=5), min=runif(10)) 
df1 = mutate(df1, max=min+runif(10)) 
df2 = data.frame(letters=rep(letters[1:2], 25), position=runif(50), val=rnorm(50)) 

对于df1每一行,我想计算所有df2$val其中df2$positiondf1$min和之间的总和df1$max AND df2$letters等于df1$letter

this question on SO,我可以做调理的第一部分(即和,df2$position之间df1$mindf1$max):

incompleteCond = df1 %>% rowwise %>% 
    mutate(sumval = sum(df2$val[between(df2$position, min, max)])) 

但这不保证df2$letters与同意的df2满足这个条件的行总结相应的df1$letter。我怎样才能在这个其他列上添加这个条件? 以下尝试不起作用:

# Note: these solutions actually DO the job with dplyr_0.4.3! 
wrong1 = df1 %>% rowwise %>% 
    mutate(sumval = 
      sum(df2$val[between(df2$position, min, max) & df2$letters==letter])) 

wrong3 = df1 %>% rowwise %>% 
    mutate(sumval = 
      sum(df2[(df2$position>=min) & (df2$position<=max) & (df2$letters==letter), 
        'val'])) 

编辑

看起来这实际上是版本的问题:从dplyr_0.4.1dplyr_0.4.3解决了这个问题,它意味着:上面的wrong1wrong3实际上是正确的(它们只给出版本为0.4.1的零)。

作为一个方面说明,我还没有找到dplyr的唯一解决方案 - 子集(filterdf2,但上述工作,以及@ r2evans的好回答也是如此。

+1

为什么不加入这两个数据集的第一? – aosmith

+0

为什么倒票?没有可重现的数据?有。没有研究工作?我真的做到了。重复?请链接。愚蠢的问题?我的确被愚蠢地阻止了一段时间,很快就需要一个解决方案 - 这是否是错误的用法?对于赞成倒票的几句解释是值得欢迎的,并且至少可以让它具有建设性。 – ztl

+0

谢谢@aosmith。因为我对此并不熟悉,所以没有真正意识到如何去做。感谢您的建议,并感谢r2evans的例子。 – ztl

回答

1

你很接近,我认为:

df1 %>% 
    rowwise() %>% 
    mutate(sumval = sum(df2$val[df2$letters == letter & between(df2$position, min, max)])) 
## Source: local data frame [10 x 4] 
## Groups: <by row> 
## letter  min  max  sumval 
## (fctr)  (dbl)  (dbl)  (dbl) 
## 1  a 0.1848823 0.7375563 -3.8432366 
## 2  a 0.7023740 0.9412688 -0.9138266 
## 3  a 0.5733263 1.3338396 4.1341039 
## 4  a 0.1680519 0.3488720 -2.5142686 
## 5  a 0.9438393 1.3491215 3.6405305 
## 6  b 0.9434750 1.7970234 -0.1416608 
## 7  b 0.1291590 1.1055575 -5.2083130 
## 8  b 0.8334488 1.0592743 1.0618699 
## 9  b 0.4680185 0.9128277 -2.3595283 
## 10  b 0.5499837 0.6249632 0.0000000 

另一种选择,如@aosmith建议,是先加入这两个数据集。可能注意到

df1 %>% 
    mutate(grp = 1:n()) %>% 
    left_join(df2, by=c('letter'='letters')) %>% 
    filter(position >= min & position <= max) %>% 
    group_by(grp) %>% 
    summarize(letter=letter[1], min=min[1], max=max[1], sumval=sum(val)) %>% 
    select(-grp) 
## Source: local data frame [9 x 4] 
## letter  min  max  sumval 
## (fctr)  (dbl)  (dbl)  (dbl) 
## 1  a 0.1848823 0.7375563 -3.8432366 
## 2  a 0.7023740 0.9412688 -0.9138266 
## 3  a 0.5733263 1.3338396 4.1341039 
## 4  a 0.1680519 0.3488720 -2.5142686 
## 5  a 0.9438393 1.3491215 3.6405305 
## 6  b 0.9434750 1.7970234 -0.1416608 
## 7  b 0.1291590 1.1055575 -5.2083130 
## 8  b 0.8334488 1.0592743 1.0618699 
## 9  b 0.4680185 0.9128277 -2.3595283 

一个区别是,最后的“B”组不包括在后一类,因为没有数据在给定范围内。

编辑:从使用between(其不向量化的最小值/最大值的参数),以更简单的向量比较,否定使用rowwise的性能惩罚改变了加入代码。我也删除了ungroup,因为在summarize之后,分组无论如何都被移除了。

FYI:

sessionInfo() 
## R version 3.2.2 (2015-08-14) 
## Platform: x86_64-w64-mingw32/x64 (64-bit) 
## Running under: Windows 8 x64 (build 9200) 
## locale: 
## [1] LC_COLLATE=English_United States.1252 
## [2] LC_CTYPE=English_United States.1252 
## [3] LC_MONETARY=English_United States.1252 
## [4] LC_NUMERIC=C       
## [5] LC_TIME=English_United States.1252  
## attached base packages: 
## [1] stats  graphics grDevices utils  datasets methods base  
## other attached packages: 
## [1] dplyr_0.4.3 
## loaded via a namespace (and not attached): 
## [1] compiler_3.2.2 lazyeval_0.1.10 magrittr_1.5 R6_2.1.1  
## [5] assertthat_0.1 parallel_3.2.2 tools_3.2.2  DBI_0.3.1  
## [9] htmltools_0.2.6 Rcpp_0.12.1  rmarkdown_0.8.1 digest_0.6.8 
+0

我在这个和更大的数据集上做了一个快速的'microbenchmark'(实际上是给我自己定制的),对于更小的集合,它看起来像'rowwise'方法稍微快一点;对于较大的数据集,“join”方法更快,时间缩短40%。不是基准就是一切,但是如果你有很多数据,也许第二个更详细的代码将是首选。 – r2evans

+0

谢谢@ r2evans。解决方案2工作正常,但非常奇怪的解决方案1给我一个“sumval”列只有零...?!当我在原始数据集上搜索解决方案时,这也发生了......您正在使用哪个版本的'dplyr'? [注意:对于解决方案1,第3行是'df2 $ letters'(缺少's'),是不是?] – ztl

+0

其实,@ r2evans,你的解决方案1与我的'wrong1'有什么不同?检查一下,'wrong1'也只给出了我的零,就像你的解决方案1一样(而且它们看起来和我完全一样,超出了条件的顺序)。因此,两者似乎都没问题,现在的问题是要明白为什么它会这样对我......?!任何想法/建议?我错过了什么? – ztl