R dplyr: วางหลายคอลัมน์


97

ฉันมี dataframe และรายการคอลัมน์ใน dataframe ที่ฉันต้องการทิ้ง ลองใช้irisชุดข้อมูลเป็นตัวอย่าง ฉันต้องการที่จะลดลงSepal.LengthและSepal.Widthและใช้เฉพาะคอลัมน์ที่เหลือ ฉันจะทำสิ่งนี้โดยใช้selectหรือselect_จากdplyrแพ็คเกจได้อย่างไร?

นี่คือสิ่งที่ฉันได้ลองทำแล้ว:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

ข้อผิดพลาดใน -drop.cols: อาร์กิวเมนต์ไม่ถูกต้องสำหรับตัวดำเนินการยูนารี

iris %>% select_(.dots = -drop.cols)

ข้อผิดพลาดใน -drop.cols: อาร์กิวเมนต์ไม่ถูกต้องสำหรับตัวดำเนินการยูนารี

iris %>% select(!drop.cols)

เกิดข้อผิดพลาดใน! drop.cols: ประเภทอาร์กิวเมนต์ไม่ถูกต้อง

iris %>% select_(.dots = !drop.cols)

เกิดข้อผิดพลาดใน! drop.cols: ประเภทอาร์กิวเมนต์ไม่ถูกต้อง

ฉันรู้สึกว่าฉันพลาดอะไรบางอย่างที่ชัดเจนเพราะสิ่งเหล่านี้ดูเหมือนเป็นการดำเนินการที่มีประโยชน์ซึ่งควรมีอยู่แล้ว ใน Github มีคนโพสต์ปัญหาที่คล้ายกันและ Hadley บอกว่าให้ใช้ 'การสร้างดัชนีเชิงลบ' นั่นคือสิ่งที่ (ฉันคิด) ฉันได้ลองแล้ว แต่ก็ไม่เกิดประโยชน์อะไร ข้อเสนอแนะใด ๆ ?

คำตอบ:


129

ตรวจสอบความช่วยเหลือเกี่ยวกับ select_vars นั่นทำให้คุณมีแนวคิดพิเศษในการทำงานกับสิ่งนี้

ในกรณีของคุณ:

iris %>% select(-one_of(drop.cols))

ขอบคุณ. ด้วยเหตุผลบางประการสิ่งนี้ใช้งานirisได้ แต่ไม่ใช่ในดาต้าเฟรมจริงของฉัน ( irisเป็นตัวอย่างของเล่น) ดาต้าเฟรมของฉันมี 4558 แถวและ 147 คอลัมน์ Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytesข้อผิดพลาดที่ผมได้รับคือ มีความคิดว่าเหตุใดจึงอาจเกิดขึ้น
Navaneethan Santhanam

1
อาดูเหมือนว่าฉันจะทำผิดพลาด ฉันบังเอิญใช้select_varsแทนselect. ตอนนี้มันทำงานได้อย่างสมบูรณ์!
Navaneethan Santhanam

6
เราจะหาข้อมูลเกี่ยวกับฟังก์ชัน inbuilt ได้one_ofที่ไหน? เว้นแต่ฉันจะขาดบางสิ่งบางอย่างที่ไม่ปรากฏในเอกสารประกอบแพ็คเกจ ( help(package='dplyr'))
geotheory

4
@geotheory มีเอกสาร one_of จริงๆ ดูhelp(one_of, package = "dplyr"). อย่างน้อยก็อยู่ในแพ็คเกจเวอร์ชัน 0.5.0 แต่ช่วยในการอ่านบล็อกที่ Hadley โพสต์เมื่อมีการอัปเดตแพ็คเกจหนึ่งของเขา และบางฟังก์ชันจะถูกบันทึกไว้ในฟังก์ชันอื่น ๆ น่าเสียดายที่ต้องอ่านเอกสารทั้งหมดซึ่งส่วนใหญ่ฉันจะทำเมื่อต้องการสิ่งที่ไม่ชัดเจนหรือเป็นไปได้ในทันทีด้วยฟังก์ชัน
phiver

11
ขอบคุณ. คุณจะทราบเกี่ยวกับฟังก์ชันเหล่านี้ได้อย่างไรในตอนแรกในแง่ของเอกสาร
geotheory


38

นอกจากนี้select(-one_of(drop.cols))ยังมีตัวเลือกอื่น ๆ อีกสองสามตัวสำหรับการวางคอลัมน์โดยใช้select()ที่ไม่เกี่ยวข้องกับการกำหนดชื่อคอลัมน์เฉพาะทั้งหมด (ใช้ข้อมูลตัวอย่าง dplyr starwars สำหรับชื่อคอลัมน์ที่หลากหลาย):

starwars %>% 
  select(-(name:mass)) %>%        # the range of columns from 'name' to 'mass'
  select(-contains('color')) %>%  # any column name that contains 'color'
  select(-starts_with('bi')) %>%  # any column name that starts with 'bi'
  select(-ends_with('er')) %>%    # any column name that ends with 'er'
  select(-matches('^f.+s$')) %>%  # any column name matching the regex pattern
  select_if(~!is.list(.)) %>%     # not by column name but by data type
  head(2)

# A tibble: 2 x 2
homeworld species
  <chr>     <chr>  
1 Tatooine  Human  
2 Tatooine  Droid 

คือselect_if(~!is.list(.))เทียบเท่ากับselect_if(is.list(.))?
Jasha

3
ในกรณีนี้~คือการชวเลขฟอร์เรนสำหรับการกำหนดฟังก์ชันที่ไม่ระบุชื่อไม่ใช่สัญลักษณ์อื่นสำหรับไม่ ยกตัวอย่างเช่นทั้งสองหมายถึงสิ่งเดียวกันและfunction(x) {!is.list(x)} ~!is.list(.)คิดว่าเป็นชวเลข~ function(.)
SlyFox

8

โปรดใช้ความระมัดระวังกับselect()ฟังก์ชันนี้เนื่องจากใช้ทั้งในแพ็คเกจ dplyr และ MASS ดังนั้นหากโหลด MASS ให้เลือก () อาจทำงานไม่ถูกต้อง หากต้องการทราบว่ามีการโหลดแพ็กเกจใดบ้างให้พิมพ์sessionInfo()และค้นหาในส่วน "แพ็กเกจอื่น ๆ ที่แนบมา:" หากโหลดแล้วให้พิมพ์detach( "package:MASS", unload = TRUE )และselect()ฟังก์ชันของคุณจะทำงานได้อีกครั้ง


12
หรือคุณสามารถเข้าถึงฟังก์ชันโดยตรงในเนมสเปซแพ็กเกจdplyr::select()ได้
Triamus

2
ฉันพบปัญหานี้บ่อยเกินไป dselect <- dplyr::select()ตอนนี้ผมมักจะกำหนดฟังก์ชั่นใหม่ที่ด้านบนของสคริปต์ของฉัน
filups21

6

เราสามารถลอง

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))

ขอบคุณ @akrun สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบ อย่างไรก็ตามด้วยdplyrความสามารถรอบข้างในการทำให้งานวิเคราะห์พื้นฐานง่ายต่อการอ่านและเขียนฉันผิดหวังที่โซลูชันจริงดูเหมือนวิธีแก้ปัญหา
Navaneethan Santhanam

@NavaneethanSanthanam จริงๆแล้วone_ofทางออกอื่น ๆ คือหนทางที่จะไป ฉันลืมมันไปแล้ว
akrun

3

อีกวิธีหนึ่งคือการเปลี่ยนคอลัมน์ที่ไม่ต้องการเพื่อNULLหลีกเลี่ยงวงเล็บที่ฝังไว้:

head(iris,2) %>% mutate_at(drop.cols, ~NULL)
#   Petal.Length Petal.Width Species
# 1          1.4         0.2  setosa
# 2          1.4         0.2  setosa

นอกจากนี้ยังไม่แจ้งเตือนหากไม่มีคอลัมน์
skoz

3

หากคุณมีอักขระพิเศษในชื่อคอลัมน์อาจเป็นไปได้selectหรือselect_ไม่ทำงานตามที่คาดไว้ คุณสมบัติของdplyrการใช้งาน"."นี้ หากต้องการอ้างถึงชุดข้อมูลในคำถามคุณสามารถใช้บรรทัดต่อไปนี้เพื่อแก้ปัญหานี้:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]

ไม่แนะนำให้ใช้รหัสคำตอบเท่านั้น โปรดให้คำอธิบายเกี่ยวกับวิธีการทำงานของคำตอบและความแตกต่างจากคำตอบที่มีอยู่แล้ว
Ralf Stubner

ขอขอบคุณ!! วิธีแก้ปัญหาอื่น ๆ ข้างต้นไม่ได้ผลสำหรับเหตุผลที่แน่นอนนี้
Marty999

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