2015-11-06 48 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