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.