2014-02-07 76 views
89

有沒有一種更簡潔的方式來從一個數據庫後端的tbl中獲得一列dplyr tbl作爲一個向量(即數據框/表不能直接被子集)?提取一個dplyr tbl列作爲一個向量

require(dplyr) 
db <- src_sqlite(tempfile(), create = TRUE) 
iris2 <- copy_to(db, iris) 
iris2$Species 
# NULL 

那將是太容易了,所以

collect(select(iris2, Species))[, 1] 
# [1] "setosa"  "setosa"  "setosa"  "setosa" etc. 

但似乎有點笨拙。

+0

是'收集(IRIS2)$ Species'少笨拙? –

回答

53

隨着dplyr 0.7.0,您可以使用pull獲得從tbl載體。


library("dplyr") 
#> 
#> Attaching package: 'dplyr' 
#> The following objects are masked from 'package:stats': 
#> 
#>  filter, lag 
#> The following objects are masked from 'package:base': 
#> 
#>  intersect, setdiff, setequal, union 
db <- src_sqlite(tempfile(), create = TRUE) 
iris2 <- copy_to(db, iris) 
vec <- pull(iris2, Species) 
head(vec) 
#> [1] "setosa" "setosa" "setosa" "setosa" "setosa" "setosa" 
17

我可能會寫:

collect(select(iris2, Species))[[1]] 

由於dplyr是專爲數據的tbls工作,有沒有更好的方式來獲得數據的單個列。

+0

不能說比這更公平。當我嘗試使用唯一(表$列)來檢查虛假值時,它在控制檯中交互式地出現。 – nacnudus

+4

@nacnudus對於這種情況下,你也可以做'GROUP_BY(列)%。%理貨()' – hadley

+0

你能解釋一下這是如何工作?我不明白。 – rrs

64

按照從@nacnudus的評論,它看起來像一個pull函數,dplyr 0.6實現:

iris2 %>% pull(Species) 

對於舊版本的dplyr的,這裏有一個整潔的功能,使拉出列有點更好(更容易輸入,更容易閱讀):

pull <- function(x,y) {x[,if(is.name(substitute(y))) deparse(substitute(y)) else y, drop = FALSE][[1]]} 

這讓你做任一:

iris2 %>% pull('Species') 
iris2 %>% pull(Species) 
iris2 %>% pull(5) 

在...

[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4 

得到的它也能正常工作與數據幀:

> mtcars %>% pull(5) 
[1] 3.90 3.90 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 3.92 3.07 3.07 3.07 2.93 3.00 3.23 4.08 4.93 4.22 3.70 2.76 3.15 3.73 3.08 4.08 4.43 
[28] 3.77 4.22 3.62 3.54 4.11 

一個很好的方式在dplyr V0.2做到這一點:

iris2 %>% select(Species) %>% collect %>% .[[5]] 

或者如果你p參考:

iris2 %>% select(Species) %>% collect %>% .[["Species"]] 

或者,如果你的表是不是太大了,簡直......

iris2 %>% collect %>% .[["Species"]] 
+2

我喜歡你的拉功能。我只是添加了一個案件簡化那裏是隻有一個變量:'拉< - 功能(X,Y){ 如果點(NcoI(X)== 1)Y < - 1,否則Ÿ X [,如果(是。名稱(替代(Y)))deparse(替代(Y))其他Y,下降= FALSE] [[1]] }'這樣你就可以用'去IRIS2%>%拉()' – Rappster

+6

您還可以使用'magrittr'說明符運算符('%$%')從數據框中提取一個向量。即'iris2%>%select(Species)%>%collect()%$%Species'。 – seasmith

+0

@ Luke1018你應該從這個註釋中創建一個答案 – rrs

18

我會用從magrittrextract2方便的功能:

library(magrittr) 
library(dplyr) 

iris2 %>% 
    select(Species) %>% 
    extract2(1) 
+0

你是否想要使用'collect() 'select'和'extract2'之間? – nacnudus

+9

'use_series(Species)'可能更具可讀性。感謝提醒我這些功能,還有其他幾個方便的功能。 – nacnudus

49

你也可以使用unlist,我發現它更易於閱讀,因爲您不需要重複列的名稱或指定索引。

iris2 %>% select(Species) %>% unlist(use.names = FALSE) 
+0

簡單而高效,謝謝! – Melka

+1

這似乎是最通用的方法,因爲它與載體和data.frames同樣工作,即,它能夠使功能更加不可知的。 – geotheory

+0

我只是在尋找這個確切問題的答案,而'unlist'正是我所需要的。謝謝! –

7

@ Luke1018提出了一個評論此解決方案:

您還可以使用magrittr博覽會操作(%$%)從數據幀拉載體。

例如:

iris2 %>% select(Species) %>% collect() %$% Species 

我認爲它值得自己的答案。

+0

我一直在尋找這個。 – Diego

+0

如果我想傳遞不是colname本身,而是包含它的字符串變量,我該怎麼做? – mzuba