แตกคอลัมน์ dplyr tbl เป็นเวกเตอร์


175

มีวิธีที่ชัดเจนมากขึ้นในการรับหนึ่งคอลัมน์ของ dplyr tbl เป็นเวกเตอร์จาก 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.

แต่ดูเหมือนจะเงอะงะนิดหน่อย


เป็นcollect(iris2)$Speciesเงอะงะน้อยลงหรือไม่
CJ Yetman

คำตอบ:


178

ด้วย dplyr 0.7.0 คุณสามารถใช้ที่จะได้รับจากเวกเตอร์ที่pulltbl


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 ดูเหมือนว่ามี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

วิธีที่ดีในการทำเช่นนี้ใน v0.2 จากdplyr:

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

หรือถ้าคุณต้องการ:

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

หรือถ้าโต๊ะของคุณไม่ใหญ่เกินไปเพียงแค่ ...

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

2
ฉันชอบฟังก์ชั่นดึงของคุณ ฉันจะเพิ่มการทำให้เข้าใจง่ายอย่างเดียวสำหรับกรณีที่มีเพียงตัวแปรเดียว: 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]] }คุณสามารถไปด้วยiris2 %>% pull()
Rappster

7
คุณยังสามารถใช้ตัวmagrittrดำเนินการการแสดงออก ( %$%) เพื่อดึงเวกเตอร์จาก data frame iris2 %>% select(Species) %>% collect() %$% Speciesกล่าวคือ
seasmith

@ Luke1018 คุณควรสร้างคำตอบจากความคิดเห็นนี้
rrs

pull()จะดำเนินการในรุ่น dplyr 0.6 github.com/tidyverse/dplyr/commit/…
nacnudus

72

คุณสามารถใช้unlistสิ่งที่ฉันอ่านง่ายขึ้นเพราะคุณไม่จำเป็นต้องทำซ้ำชื่อของคอลัมน์หรือระบุดัชนี

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

1
นี่ดูเหมือนว่าเป็นวิธีการที่หลากหลายที่สุดในการทำงานเหมือนกันกับเวกเตอร์และ data.frames
geotheory

ฉันแค่มองหาคำตอบสำหรับคำถามนี้และunlistเป็นสิ่งที่ฉันต้องการ ขอบคุณ!
Andrew Brēza

unlistยังสามารถแยกค่าจากหลายคอลัมน์ (รวมค่าทั้งหมดเป็นเวกเตอร์เดียว) ในขณะที่dplyr::pullถูก จำกัด ไว้ที่คอลัมน์เดียว
filups21

21

ฉันจะใช้extract2ฟังก์ชั่นอำนวยความสะดวกจากmagrittr:

library(magrittr)
library(dplyr)

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

คุณหมายถึงใช้collect()ระหว่างselectและextract2?
nacnudus

10
use_series(Species)อาจจะอ่านได้มากขึ้น ขอบคุณที่แจ้งเตือนฉันถึงฟังก์ชั่นเหล่านี้มีประโยชน์อีกหลายอย่างที่มาจาก
nacnudus

20

ฉันอาจจะเขียน:

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

เนื่องจาก dplyr ถูกออกแบบมาเพื่อทำงานกับข้อมูล tbls จึงไม่มีวิธีที่ดีกว่าในการรับข้อมูลคอลัมน์เดียว


ไม่สามารถพูดได้ยุติธรรมกว่านั้น มันเกิดขึ้นแบบโต้ตอบในคอนโซลเมื่อฉันพยายามใช้เฉพาะ (คอลัมน์ $ table) เพื่อตรวจสอบค่าปลอม
nacnudus

4
@nacnudus สำหรับกรณีนี้คุณสามารถทำได้group_by(column) %.% tally()
hadley

12
การโต้เถียงdrop = TRUEที่dplyr::selectจะน่าทึ่งสำหรับกรณีการใช้งานจำนวนมากที่เราจำเป็นต้องดึงเวกเตอร์
แอนทอนLizée

นี่เป็นวิธีเดียวที่ฉันจะเอาคอลัมน์ออกจากไฟล์ Sparklyr ของฉัน ดึงไม่ทำงานสำหรับฉันในรุ่น 0.7.8
Meep

16

@ Luke1018 เสนอวิธีแก้ไขปัญหานี้ในหนึ่งในความคิดเห็น:

คุณยังสามารถใช้ตัวmagrittrดำเนินการการแสดงออก ( %$%) เพื่อดึงเวกเตอร์จาก data frame

ตัวอย่างเช่น:

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

ฉันคิดว่ามันสมควรคำตอบของตัวเอง


ฉันกำลังมองหาสิ่งนี้
Diego-MX

ฉันจะทำสิ่งนี้ได้อย่างไรถ้าฉันต้องการผ่าน colname เองไม่ใช่ตัวแปรสตริงที่มีอยู่
mzuba

@mzuba tibble(x = 1:10, y = letters[1:10]) %>% select_("x") %>% unlist()และคุณสามารถเพิ่มอีกได้%>% unname()ในตอนท้ายหากคุณต้องการ แต่สำหรับวัตถุประสงค์ของฉันฉันไม่พบว่าการเชื่อมโยงไปป์ไลน์ครั้งสุดท้ายนั้นจำเป็น คุณสามารถระบุuse.names = FALSEในunlist()คำสั่งซึ่งทำสิ่งเดียวกันกับการเพิ่มunname()ลงใน chain chain
Mark White

1
@mzuba ฉันจะใช้pullคำสั่งตอนนี้ โซลูชันของฉันเขียนขึ้นก่อนdplyrเวอร์ชัน 0.6
rrs

1
โปรดทราบว่าใช้%$%งานได้กับทุกรายการ แต่pull()ไม่สามารถ
ทำได้

2

หากคุณคุ้นเคยกับการใช้วงเล็บเหลี่ยมสำหรับการจัดทำดัชนีตัวเลือกอื่นคือเพียงห่อวิธีการทำดัชนีตามปกติในการเรียกไปยังdeframe ()เช่น:

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

อันนั้นและpull ()เป็นวิธีที่ดีในการรับคอลัมน์ tibble

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.