Vektör olarak bir dplyr tbl sütununu çıkarma


175

Veritabanı arka uçlu bir tbl'den bir vektör olarak bir dplyr tbl sütunu almanın daha özlü bir yolu var mı (yani veri çerçevesi / tablosu doğrudan alt küme olamaz)?

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

Bu çok kolay olurdu, yani

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

Ama biraz sakar görünüyor.


daha collect(iris2)$Speciesaz sakar mı?
CJ Yetman

Yanıtlar:


179

Dplyr 0.7.0 ile, pulla 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"

96

@Nacnudus'un yorumuna göre, bir pullişlev dplyr 0.6'da uygulanmış gibi görünüyor :

iris2 %>% pull(Species)

Dplyr'in eski sürümleri için, bir sütunu biraz daha hoş hale getirmek için (düzgün bir şekilde yazılması ve okunması daha kolay) düzgün bir işlev vardır:

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

Bu, aşağıdakilerden birini yapmanızı sağlar:

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

Sonuçlanan...

 [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

Ayrıca veri çerçeveleri ile de iyi çalışır:

> 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

Bunun v0.2'sinde bunu yapmanın güzel bir yolu dplyr :

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

İsterseniz:

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

Ya da masanız çok büyük değilse ...

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

2
Çekme fonksiyonunu seviyorum. Sadece bir değişkenin olduğu durumlar için sadece bir sadeleştirme ekleyeceğim: pull <- function(x, y) { if (ncol(x) == 1) y <- 1 else y x[ , if (is.name(substitute(y))) deparse(substitute(y)) else y, drop = FALSE][[1]] }böylece gidebilirsiniziris2 %>% pull()
Rappster

7
Veri çerçevesinden bir vektör çekmek için magrittrdışa aktarma işlecini ( %$%) de kullanabilirsiniz . yani iris2 %>% select(Species) %>% collect() %$% Species.
denizci

Luke1018 @ Bu yorumun bir cevap oluşturmalıdır
RRS

pull()dplyr 0.6 sürümünde uygulanacak github.com/tidyverse/dplyr/commit/…
nacnudus

72

Ayrıca unlist, sütunun adını tekrarlamanız veya dizini belirtmeniz gerekmediği için okumayı daha kolay bulduğumu da kullanabilirsiniz .

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

1
Bu, vektörler ve data.frames ile aynı şekilde çalıştığı için en çok yönlü yöntem gibi görünüyor, yani işlevlerin daha agnostik olmasını sağlıyor.
geotheory

Ben sadece bu tam sorunun cevabını arıyordum ve unlisttam da ihtiyacım olan buydu. Teşekkürler!
Andrew Brēza

unlistaynı zamanda birden çok sütundan değerleri çıkarabilir (tüm değerleri tek bir vektöre birleştirerek), ancak dplyr::pulltek bir sütunla sınırlıdır.
filups21

21

Ben extract2kolaylık fonksiyonu kullanmak istiyorsunuz magrittr:

library(magrittr)
library(dplyr)

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

Kullanmak kastettiniz collect()arasında selectve extract2?
nacnudus

10
use_series(Species)belki daha da okunabilir. Beni bu işlevler konusunda uyardığınız için teşekkürler, bunun geldiği birkaç kullanışlı işlev daha var.
nacnudus

20

Muhtemelen şunu yazardım:

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

Dplyr, tbls veri ile çalışmak üzere tasarlandığından, tek bir veri sütunu almanın daha iyi bir yolu yoktur.


Bundan daha adil diyemeyiz. Sahte değerleri kontrol etmek için benzersiz (tablo $ sütun) kullanmayı denediğimde konsolda etkileşimli olarak ortaya çıktı.
nacnudus

4
@nacnudus da yapabilirsingroup_by(column) %.% tally()
hadley

12
Bir tartışma drop = TRUEiçin dplyr::selectbiz aslında vektörleri ayıklamak gerek oldukça birçok kullanım durumları için şaşırtıcı olurdu.
Antoine Lizée

Sparklyr sdf'mden bir sütun alabilmemin tek yolu buydu. Pull 0.7.8 sürümünde benim için çalışmadı.
Meep

17

@ Luke1018 bu çözümü şu yorumlardan birinde önerdi:

Veri çerçevesinden bir vektör çekmek için magrittrdışa aktarma işlecini ( %$%) de kullanabilirsiniz .

Örneğin:

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

Kendi cevabını hak ettiğini düşündüm.


Bunu arıyordum.
Diego-MX

Colname kendisi değil onu içeren bir dize değişkeni geçmek istiyorum, bunu nasıl yapabilirim?
mzuba

mzuba tibble(x = 1:10, y = letters[1:10]) %>% select_("x") %>% unlist()ve isterseniz %>% unname()sonuna bir tane daha ekleyebilirsiniz , ama benim amacım için bu son boru zinciri bağlantısının gerekli olduğunu bulamadım. Ayrıca belirtebilirsiniz use.names = FALSEiçinde unlist()de eklemekle aynı şeyi yapar komuta, unname()boru zinciri üzerine.
Mark White

1
@mzuba pullŞimdi komutu kullanacağım . dplyrÇözümüm 0.6 sürümünden önce yazılmıştı .
rrs

1
Not olduğunu %$%, oysa her listede eserler pull()değil
wint3rschlaefer

3

İndeksleme için köşeli parantez kullanmaya alışıksanız , başka bir seçenek de normal bir indeksleme yaklaşımını deframe () çağrısında sarmaktır , örneğin:

library(tidyverse)

iris2 <- as_tibble(iris)

# using column name
deframe(iris2[, 'Sepal.Length'])

# [1] 5.1 4.9 4.7 4.6 5.0 5.4

# using column number
deframe(iris2[, 1])

# [1] 5.1 4.9 4.7 4.6 5.0 5.4

Bu ve pull () , bir tibble sütunu almanın oldukça iyi yoludur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.