เลือกเฉพาะคอลัมน์ตัวเลขจากกรอบข้อมูล


189

สมมติว่าคุณมี data.frame เช่นนี้:

x <- data.frame(v1=1:20,v2=1:20,v3=1:20,v4=letters[1:20])

คุณจะเลือกเฉพาะคอลัมน์เหล่านั้นใน x ที่เป็นตัวเลขได้อย่างไร

คำตอบ:


289

แก้ไข: อัปเดตเพื่อหลีกเลี่ยงการใช้คำแนะนำที่ไม่ดี sapplyไม่ดี

เนื่องจาก data frame เป็นรายการเราจึงสามารถใช้ฟังก์ชัน list-apply:

nums <- unlist(lapply(x, is.numeric))  

จากนั้นการตั้งค่ามาตรฐานแบบย่อย

x[ , nums]

## don't use sapply, even though it's less code
## nums <- sapply(x, is.numeric)

สำหรับ R ที่ทันสมัยมากขึ้นตอนนี้ฉันขอแนะนำ

x[ , purrr::map_lgl(x, is.numeric)]

codey น้อยกว่าสะท้อนให้เห็นถึงนิสัยใจคอที่เฉพาะเจาะจงของ R และตรงไปตรงมามากขึ้นและมีประสิทธิภาพในการใช้กับ tibbles ฐานข้อมูลด้านหลัง:

dplyr::select_if(x, is.numeric)

10
x[nums]หรือx[sapply(x,is.numeric)]ทำงานได้ดี data.frameและพวกเขามักจะกลับมา เปรียบเทียบx[1]กับx[,1]- แรกคือdata.frameที่สองคือเวกเตอร์ x[, 1, drop=FALSE]หากหนึ่งต้องการที่จะป้องกันไม่ให้เกิดการแปลงแล้วจะต้องใช้
Marek

วิธีใดในการเลือกข้อมูลต่อเนื่องเท่านั้น วิธีนี้จะส่งกลับอย่างต่อเนื่องเช่นเดียวกับจำนวนเต็ม
Derelict

undefined columns selectedเมื่อไม่มีคอลัมน์ตัวเลขข้อผิดพลาดต่อไปนี้เกิดขึ้น คุณจะหลีกเลี่ยงได้อย่างไร
โยฮันโอบาดี

@SoilSciGuy ข้อมูลอย่างต่อเนื่องควรเป็นตัวเลข บางทีคุณอาจมีข้อมูลปัจจัยที่อยู่ในรูปแบบตัวเลข? คุณควรเปิดคำถามใหม่
Brandon Bertelsen

1
@YohanObadia คุณสามารถใช้tryCatch()เพื่อจัดการกับสิ่งนี้ โปรดพิจารณาเปิดคำถามใหม่
Brandon Bertelsen


44

Filter() จากแพ็คเกจพื้นฐานเป็นฟังก์ชั่นที่สมบูรณ์แบบสำหรับกรณีการใช้งาน: คุณต้องใช้รหัส:

Filter(is.numeric, x)

มันเร็วกว่าselect_if():

library(microbenchmark)
microbenchmark(
    dplyr::select_if(mtcars, is.numeric),
    Filter(is.numeric, mtcars)
)

ส่งคืน (บนคอมพิวเตอร์ของฉัน) เป็นค่ามัธยฐาน 60 microseconds Filterและ 21 000 microseconds สำหรับselect_if(เร็วกว่า 350x)


วิธีนี้จะไม่ล้มเหลวเมื่อไม่มีคอลัมน์ตัวเลข มีข้อ จำกัด ในการใช้งานหรือไม่?
bli

ตัวกรองจะใช้กับแถวของดาต้าเฟรมแทนที่จะเป็นคอลัมน์เท่านั้น ดังนั้นวิธีนี้จะไม่ให้ผลลัพธ์ที่ถูกต้อง
Michael

4
@Michael ไม่สับสนกรองจากแพคเกจฐานและกรองจากแพคเกจ dplyr!
Kevin Zarca

1
@bli ฉันไม่เห็นข้อเสียเปรียบในการใช้งานตัวกรอง อินพุตเป็นวัตถุ data.frame และส่งคืน data.frame
Kevin Zarca

เพียงแค่ตีที่นี่เพื่ออ้างอิง: สิ่งที่ใช้Filter()ไม่ได้สำหรับที่นี่คือการแทนที่เช่นFilter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris)จะไม่ทำงาน
Mobeus ซูม


5

นี่เป็นรหัสสำรองสำหรับคำตอบอื่น ๆ :

x[, sapply(x, class) == "numeric"]

กับ data.table

x[, lapply(x, is.numeric) == TRUE, with = FALSE]

3
นี่เป็นความคิดเห็นต่อคำตอบที่เลือกมากกว่าคำตอบที่ไม่ซ้ำ
Brandon Bertelsen

2
คอลัมน์สามารถมีมากกว่าหนึ่งคลาส
Rich Scriven


2

PCAmixdata ไลบรารีมี functionalon splitmix ที่แยกปริมาณ (ข้อมูลตัวเลข) และเชิงคุณภาพ (ข้อมูลเชิงหมวดหมู่) ของ dataframe ที่กำหนด "YourDataframe" ตามที่แสดงด้านล่าง:

install.packages("PCAmixdata")
library(PCAmixdata)
split <- splitmix(YourDataframe)
X1 <- split$X.quanti(Gives numerical columns in the dataset) 
X2 <- split$X.quali (Gives categorical columns in the dataset)

2

วิธีอื่นอาจเป็นดังนี้: -

#extracting numeric columns from iris datset
(iris[sapply(iris, is.numeric)])

1
สวัสดี Ayushi นี่อาจลดลงเพราะเป็นคำตอบแรกซ้ำ แต่วิธีนี้มีปัญหาบางอย่างที่ระบุ ดูความคิดเห็นในคำตอบแรกคุณจะเห็นว่าฉันหมายถึงอะไร
Brandon Bertelsen

1

หากคุณมีตัวแปรปัจจัยมากมายคุณสามารถใช้ select_if funtion ติดตั้งแพ็คเกจ dplyr มีฟังก์ชั่นมากมายที่แยกข้อมูลโดยการทำเงื่อนไข คุณสามารถกำหนดเงื่อนไข

ใช้แบบนี้

categorical<-select_if(df,is.factor)
str(categorical)

2
ดูเหมือนคำตอบที่ซ้ำกันก่อนหน้านี้stackoverflow.com/a/40808873/170352
Brandon Bertelsen

0

นี่ไม่ได้ตอบคำถามโดยตรง แต่มีประโยชน์มากโดยเฉพาะถ้าคุณต้องการบางอย่างเช่นคอลัมน์ตัวเลขยกเว้นคอลัมน์ id และตัวแปรตาม

numeric_cols <- sapply(dataframe, is.numeric) %>% which %>% 
                   names %>% setdiff(., c("id_variable", "dep_var"))

dataframe %<>% dplyr::mutate_at(numeric_cols, function(x) your_function(x))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.