Ekstrak kolom tbl dplyr sebagai vektor


175

Apakah ada cara yang lebih ringkas untuk mendapatkan satu kolom dplyr tbl sebagai vektor, dari tbl dengan database back-end (mis. Frame data / tabel tidak dapat diatur secara langsung)?

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

Itu akan terlalu mudah, jadi

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

Tapi sepertinya agak canggung.


adalah collect(iris2)$Specieskurang kikuk?
CJ Yetman

Jawaban:


178

Dengan dplyr 0.7.0, Anda dapat menggunakan pulluntuk mendapatkan vektor dari a 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

Sesuai komentar dari @nacnudus, sepertinya ada pullfungsi yang diterapkan di dplyr 0.6:

iris2 %>% pull(Species)

Untuk versi dplyr yang lebih lama, berikut adalah fungsi yang rapi untuk membuat mengeluarkan kolom sedikit lebih bagus (lebih mudah untuk mengetik, dan lebih mudah dibaca):

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

Ini memungkinkan Anda melakukan salah satu dari ini:

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

Yang menghasilkan...

 [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

Dan itu juga berfungsi dengan baik dengan bingkai data:

> 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

Cara yang bagus untuk melakukan ini di v0.2 dari dplyr:

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

Atau jika Anda lebih suka:

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

Atau jika meja Anda tidak terlalu besar, cukup ...

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

2
Saya suka fungsi tarikan Anda. Saya hanya akan menambahkan satu penyederhanaan untuk kasus-kasus di mana hanya ada satu variabel: 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]] }sehingga Anda dapat pergi denganiris2 %>% pull()
Rappster

7
Anda juga dapat menggunakan magrittroperator eksposisi ( %$%) untuk menarik vektor dari bingkai data. yaitu iris2 %>% select(Species) %>% collect() %$% Species.
seasmith

@ Luke1018 Anda harus membuat jawaban dari komentar ini
rrs

pull()akan diimplementasikan dalam versi dplyr
nacnudus

72

Anda juga dapat menggunakan unlistyang menurut saya lebih mudah dibaca karena Anda tidak perlu mengulangi nama kolom atau menentukan indeks.

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

1
Ini tampaknya metode yang paling serbaguna karena berfungsi identik dengan vektor dan data.frame, yaitu memungkinkan fungsi menjadi lebih agnostik.
geotheory

Saya hanya mencari jawaban untuk pertanyaan yang tepat ini dan unlisttepat apa yang saya butuhkan. Terima kasih!
Andrew Brēza

unlistjuga dapat mengekstraksi nilai dari beberapa kolom (menggabungkan semua nilai ke dalam satu vektor), sementara dplyr::pullterbatas pada satu kolom.
filups21

21

Saya akan menggunakan extract2fungsi kenyamanan dari magrittr:

library(magrittr)
library(dplyr)

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

Apakah Anda bermaksud menggunakan collect()antara selectdan extract2?
nacnudus

10
use_series(Species)bahkan mungkin lebih mudah dibaca. Terima kasih telah memberi tahu saya tentang fungsi-fungsi ini, ada beberapa yang berguna dari mana datangnya.
nacnudus

20

Saya mungkin akan menulis:

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

Karena dplyr dirancang untuk bekerja dengan tbl data, tidak ada cara yang lebih baik untuk mendapatkan satu kolom data.


Tidak bisa mengatakan lebih adil dari itu. Itu muncul secara interaktif di konsol ketika saya mencoba menggunakan unik (tabel $ kolom) untuk memeriksa nilai palsu.
nacnudus

4
@nacnudus untuk kasus yang juga bisa Anda lakukangroup_by(column) %.% tally()
hadley

12
Argumen drop = TRUEuntuk dplyr::selectmenjadi luar biasa untuk banyak kasus penggunaan di mana kita benar-benar perlu mengekstraksi vektor.
Antoine Lizée

Ini adalah satu-satunya cara saya bisa mendapatkan kolom dari sdf Sparklyr saya. Pull tidak berfungsi untuk saya di versi 0.7.8.
Meep

16

@ Luke1018 mengusulkan solusi ini di salah satu komentar:

Anda juga dapat menggunakan magrittroperator eksposisi ( %$%) untuk menarik vektor dari bingkai data.

Sebagai contoh:

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

Saya pikir itu pantas dijawab sendiri.


Saya mencari ini.
Diego-MX

Bagaimana saya melakukan ini jika saya ingin meneruskan bukan colname itu sendiri tetapi variabel string yang berisi itu?
mzuba

@ Mozuba tibble(x = 1:10, y = letters[1:10]) %>% select_("x") %>% unlist()dan Anda juga bisa menambahkan yang lain %>% unname()di akhir jika Anda mau, tetapi untuk tujuan saya, saya belum menemukan bahwa link rantai pipa terakhir diperlukan. Anda juga bisa menentukan use.names = FALSEdalam unlist()perintah, yang melakukan hal yang sama seperti menambahkan unname()ke rantai pipa.
Mark White

1
@ mzuba Saya akan menggunakan pullperintah sekarang. Solusi saya ditulis sebelum dplyrversi 0.6.
rrs

1
Catatan yang %$%berfungsi pada daftar mana pun, sedangkan pull()tidak
wint3rschlaefer

2

Jika Anda terbiasa menggunakan tanda kurung siku untuk pengindeksan, opsi lain adalah dengan hanya membungkus pendekatan pengindeksan biasa dalam panggilan untuk melakukan deframe () , misalnya:

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

Itu dan tarik () keduanya cara yang cukup bagus untuk mendapatkan kolom tibble.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.