ปล่อยคอลัมน์กรอบข้อมูลตามชื่อ


874

ฉันมีคอลัมน์จำนวนหนึ่งที่ฉันต้องการลบออกจาก data frame ฉันรู้ว่าเราสามารถลบพวกเขาทีละอย่างโดยใช้สิ่งที่ชอบ:

df$x <- NULL

แต่ฉันหวังว่าจะทำสิ่งนี้ด้วยคำสั่งน้อยลง

นอกจากนี้ฉันรู้ว่าฉันสามารถวางคอลัมน์โดยใช้การทำดัชนีจำนวนเต็มเช่นนี้:

df <- df[ -c(1, 3:6, 12) ]

แต่ฉันกังวลว่าตำแหน่งสัมพัทธ์ของตัวแปรของฉันอาจเปลี่ยนแปลงได้

เมื่อพิจารณาว่า R ทรงพลังเพียงใดฉันคิดว่าอาจมีวิธีที่ดีกว่าการปล่อยแต่ละคอลัมน์ทีละหนึ่ง


13
บางคนสามารถอธิบายให้ฉันฟังได้ว่าทำไม R ไม่ได้มีอะไรที่เรียบง่ายเหมือนdf#drop(var_name)และเราจำเป็นต้องทำงานที่ซับซ้อนเหล่านี้แทน
ifly6

2
@ ifly6 ฟังก์ชั่น 'subset ()' ใน R เป็นเรื่องเกี่ยวกับการใช้คำว่า 'drop ()' ใน Python ยกเว้นคุณไม่จำเป็นต้องระบุอาร์กิวเมนต์ของแกน ... ฉันยอมรับว่ามันน่ารำคาญที่ไม่สามารถทำได้ เป็นคำหลัก / ไวยากรณ์ขั้นสูงสุดและใช้ง่ายเพียงหนึ่งเดียวที่นำมาใช้กับบอร์ดเพื่อสิ่งที่พื้นฐานเช่นเดียวกับการวางคอลัมน์
Paul Sochacki

คำตอบ:


912

คุณสามารถใช้รายการชื่อง่าย ๆ :

DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
drops <- c("x","z")
DF[ , !(names(DF) %in% drops)]

หรืออีกวิธีหนึ่งคุณสามารถสร้างรายการที่จะเก็บและอ้างอิงถึงพวกเขาด้วยชื่อ:

keeps <- c("y", "a")
DF[keeps]

แก้ไข: สำหรับผู้ที่ยังไม่คุ้นเคยกับdropอาร์กิวเมนต์ของฟังก์ชั่นการจัดทำดัชนีหากคุณต้องการให้คอลัมน์หนึ่งเป็นกรอบข้อมูลคุณต้องทำ:

keeps <- "y"
DF[ , keeps, drop = FALSE]

drop=TRUE(หรือไม่ได้กล่าวถึงมัน) yจะลดลงขนาดที่ไม่จำเป็นและด้วยเหตุนี้กลับเวกเตอร์ที่มีค่าของคอลัมน์


19
ฟังก์ชั่นชุดย่อยทำงานได้ดีขึ้นเพราะจะไม่แปลงเฟรมข้อมูลที่มีหนึ่งคอลัมน์เป็นเวกเตอร์
mut1na

3
@ mut1na ตรวจสอบอาร์กิวเมนต์หล่น = FALSE ของฟังก์ชันการทำดัชนี
Joris Meys

4
ไม่ควรที่จะเป็นDF[,keeps]แทนDF[keeps]?
lindelof

8
@lindelof ไม่สามารถทำได้ แต่คุณต้องเพิ่ม drop = FALSE เพื่อป้องกันไม่ให้ R แปลงเฟรมข้อมูลของคุณเป็นเวกเตอร์หากคุณเลือกคอลัมน์เดียว อย่าลืมว่า data frames เป็นรายการดังนั้นการเลือก list (หนึ่งมิติอย่างที่ฉันทำ) ทำงานได้อย่างสมบูรณ์แบบและส่งคืนรายการเสมอ หรือกรอบข้อมูลในกรณีนี้ซึ่งเป็นสาเหตุที่ฉันชอบที่จะใช้
Joris Meys

7
@AjayOhri ใช่มันจะ หากไม่มีเครื่องหมายจุลภาคคุณจะต้องใช้วิธี "รายการ" ในการเลือกซึ่งหมายความว่าแม้เมื่อคุณแยกคอลัมน์เดียวคุณยังคงได้รับกรอบข้อมูลกลับมา ถ้าคุณใช้วิธี "matrix" เช่นเดียวกับคุณคุณควรระวังว่าถ้าคุณเลือกคอลัมน์เดียวคุณจะได้เวกเตอร์แทน data frame เพื่อหลีกเลี่ยงปัญหานี้คุณต้องเพิ่ม drop = FALSE ตามที่อธิบายไว้ในคำตอบของฉันและในความคิดเห็นด้านบนของคุณ ...
Joris Meys

453

นอกจากนี้ยังมีsubsetคำสั่งซึ่งมีประโยชน์หากคุณรู้ว่าคุณต้องการคอลัมน์ใด:

df <- data.frame(a = 1:10, b = 2:11, c = 3:12)
df <- subset(df, select = c(a, c))

อัปเดตหลังจากความคิดเห็นโดย @hadley: หากต้องการวางคอลัมน์ a คุณสามารถทำได้:

df <- subset(df, select = -c(a, c))

3
ฉันต้องการให้subsetฟังก์ชันR มีตัวเลือกเช่น "allbut = FALSE" ซึ่ง "กลับ" การเลือกเมื่อตั้งค่าเป็น TRUE คือเก็บคอลัมน์ทั้งหมดยกเว้นที่อยู่ในselectรายการ
Prasad Chalasani

4
@prasad ดู @joris คำตอบด้านล่าง ชุดย่อยที่ไม่มีเกณฑ์ชุดย่อยใด ๆ จะมีจำนวนมากเกินไป ลองง่ายๆ:df[c("a", "c")]
JD Long

@JD ฉันรู้เรื่องนี้ แต่ฉันชอบความสะดวกสบายทางไวยากรณ์ของsubsetคำสั่งที่คุณไม่จำเป็นต้องใส่เครื่องหมายคำพูดล้อมรอบชื่อคอลัมน์ - ฉันเดาว่าฉันไม่รังเกียจที่จะพิมพ์ตัวอักษรพิเศษบางตัวเพื่อหลีกเลี่ยงการอ้างชื่อ :)
Prasad Chalasani

11
โปรดทราบว่าคุณไม่ควรใช้subsetภายในฟังก์ชั่นอื่น ๆ
Ari B. Friedman


196
within(df, rm(x))

อาจจะง่ายที่สุดหรือสำหรับหลายตัวแปร:

within(df, rm(x, y))

หรือถ้าคุณจัดการกับdata.tables (ต่อคุณจะลบคอลัมน์ตามชื่อใน data.table ได้อย่างไร? ):

dt[, x := NULL]   # Deletes column x by reference instantly.

dt[, !"x"]   # Selects all but x into a new data.table.

หรือหลายตัวแปร

dt[, c("x","y") := NULL]

dt[, !c("x", "y")]

26
within(df, rm(x))คือไกลโดยทางออกที่สะอาด ระบุว่านี่เป็นความเป็นไปได้คำตอบอื่น ๆ ดูเหมือนซับซ้อนโดยไม่จำเป็นโดยลำดับความสำคัญ
Miles Erickson

2
โปรดทราบว่าwithin(df, rm(x))จะไม่ทำงานถ้ามีคอลัมน์ที่ซ้ำกันชื่อในx df
MichaelChirico

2
@MichaelChirico ให้ความกระจ่างก็ไม่ได้ลบ แต่ดูเหมือนว่าจะเปลี่ยนค่าของข้อมูล หนึ่งมีปัญหาใหญ่ถ้าเป็นกรณีนี้ แต่ที่นี่คือตัวอย่าง: ผลตอบแทนdf <- data.frame(x = 1, y = 2); names(df) <- c("x", "x"); within(df, rm(x)) data.frame(x = 2, x = 2)
Max Ghenis

1
@MilesErickson ปัญหาคือคุณพึ่งพาฟังก์ชั่นwithin()ที่มีประสิทธิภาพ แต่ยังใช้ NSE หมายเหตุในหน้าความช่วยเหลือระบุไว้อย่างชัดเจนว่าสำหรับการเขียนโปรแกรมควรใช้ความระมัดระวังอย่างเพียงพอ
Joris Meys

@MilesErickson บ่อยครั้งที่หนึ่งจะพบดาต้าเฟรมที่มีชื่อซ้ำกันหรือไม่
HSchmale

115

คุณสามารถใช้%in%สิ่งนี้:

df[, !(colnames(df) %in% c("x","bar","foo"))]

1
ฉันขาดอะไรบางอย่างหรือนี่เป็นคำตอบเดียวกับส่วนแรกของคำตอบของ Joris หรือไม่ DF[ , !(names(DF) %in% drops)]
Daniel Fletcher

9
@DanielFletcher: มันเหมือนกัน ดูการประทับเวลาของคำตอบ เราตอบในเวลาเดียวกัน ... 5 ปีที่ผ่านมา :)
Joshua Ulrich

5
บ๊อง identical(post_time_1, post_time_2) [1] TRUE = D
Daniel Fletcher

54

รายการ (NULL) ยังใช้งานได้:

dat <- mtcars
colnames(dat)
# [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
# [11] "carb"
dat[,c("mpg","cyl","wt")] <- list(NULL)
colnames(dat)
# [1] "disp" "hp"   "drat" "qsec" "vs"   "am"   "gear" "carb"

1
ยอดเยี่ยม! สิ่งนี้ขยายการกำหนดค่า NULL ไปยังคอลัมน์เดียวในลักษณะที่เป็นธรรมชาติและ (ดูเหมือน) หลีกเลี่ยงการคัดลอก (แม้ว่าฉันไม่รู้ว่าเกิดอะไรขึ้นภายใต้ประทุนดังนั้นมันอาจไม่มีประสิทธิภาพในการใช้หน่วยความจำมากขึ้น ... แต่ดูเหมือนฉันชัดเจน มีประสิทธิภาพมากขึ้น syntactically.)
c-urchin

6
คุณไม่ต้องการรายการ (NULL), NULL ก็เพียงพอแล้ว เช่น: dat [, 4] = NULL
CousinCocaine

8
คำถามของ OP คือวิธีการลบหลายคอลัมน์ dat [, 4: 5] <- NULL จะไม่ทำงาน นั่นคือที่มาของรายการ (NULL) มันทำงานได้ตั้งแต่ 1 คอลัมน์ขึ้นไป
Vincent

สิ่งนี้ยังไม่ทำงานเมื่อพยายามลบชื่อคอลัมน์ที่ซ้ำกัน
MichaelChirico

@MichaelChirico ทำงานได้ดีสำหรับฉัน ให้ป้ายกำกับหากคุณต้องการลบคอลัมน์แรกที่มีชื่อเดียวกันหรือให้ดัชนีสำหรับแต่ละคอลัมน์ที่คุณต้องการลบ หากคุณมีตัวอย่างที่ไม่สามารถใช้งานได้ฉันสนใจที่จะดู บางทีโพสต์เป็นคำถามใหม่?
Vincent

42

หากคุณต้องการลบคอลัมน์โดยอ้างอิงและหลีกเลี่ยงการคัดลอกภายในที่เกี่ยวข้องกับdata.framesคุณสามารถใช้data.tableแพคเกจและฟังก์ชั่น:=

คุณสามารถส่งชื่อเวกเตอร์ของตัวละครไปทางซ้ายมือของ:=โอเปอเรเตอร์และNULLเป็น RHS

library(data.table)

df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)
# or more simply  DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) #

DT[, c('a','b') := NULL]

หากคุณต้องการ predefine เป็นชื่อเป็นตัวอักษรแบบเวกเตอร์นอกเรียกไป[ห่อชื่อของวัตถุใน()หรือ{}จะบังคับให้ LHS DTที่จะได้รับการประเมินอยู่ในขอบเขตการโทรไม่ได้เป็นชื่ออยู่ในขอบเขตของการ

del <- c('a','b')
DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, (del) := NULL]
DT <-  <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, {del} := NULL]
# force or `c` would also work.   

นอกจากนี้คุณยังสามารถใช้setที่หลีกเลี่ยงค่าใช้จ่ายของ[.data.table, และยังสามารถใช้ได้data.frames!

df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)

# drop `a` from df (no copying involved)

set(df, j = 'a', value = NULL)
# drop `b` from DT (no copying involved)
set(DT, j = 'b', value = NULL)

41

มีกลยุทธ์ที่มีประสิทธิภาพมากขึ้นโดยพิจารณาจากความจริงที่ว่า grep () จะส่งคืนเวกเตอร์ที่เป็นตัวเลข หากคุณมีรายการตัวแปรที่ยาวอย่างที่ฉันทำในหนึ่งในชุดข้อมูลของฉันตัวแปรบางตัวที่ลงท้ายด้วย ".A" และอื่น ๆ ที่ลงท้ายด้วย ".B" และคุณต้องการให้คนที่ลงท้ายด้วย ".A" (ตาม ด้วยตัวแปรทั้งหมดที่ไม่ตรงกับรูปแบบใดให้ทำดังนี้

dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]

สำหรับกรณีที่อยู่ในมือโดยใช้ตัวอย่าง Joris Meys มันอาจจะไม่กะทัดรัด แต่มันจะเป็น:

DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]

1
ถ้าเรากำหนดdropsในตอนแรกpaste0("^", drop_cols, "$")มันจะดีกว่ามาก (อ่าน: กะทัดรัดมากขึ้น) กับsapply:DF[ , -sapply(drops, grep, names(DF))]
MichaelChirico

30

อีกdplyrคำตอบ starts_with()หากตัวแปรของคุณมีโครงสร้างการตั้งชื่อบางส่วนร่วมกันคุณอาจจะพยายาม ตัวอย่างเช่น

library(dplyr)
df <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm (5), 
                 var4 = rnorm(5), char1 = rnorm(5), char2 = rnorm(5))
df
#        var2      char1        var4       var3       char2       var1
#1 -0.4629512 -0.3595079 -0.04763169  0.6398194  0.70996579 0.75879754
#2  0.5489027  0.1572841 -1.65313658 -1.3228020 -1.42785427 0.31168919
#3 -0.1707694 -0.9036500  0.47583030 -0.6636173  0.02116066 0.03983268
df1 <- df %>% select(-starts_with("char"))
df1
#        var2        var4       var3       var1
#1 -0.4629512 -0.04763169  0.6398194 0.75879754
#2  0.5489027 -1.65313658 -1.3228020 0.31168919
#3 -0.1707694  0.47583030 -0.6636173 0.03983268

:หากคุณต้องการที่จะลดลงตามลำดับของตัวแปรในกรอบข้อมูลที่คุณสามารถใช้ ตัวอย่างเช่นถ้าคุณต้องการที่จะลดลงvar2, var3และทุกตัวแปรในระหว่างที่คุณต้องการเพียงแค่จะเหลือvar1:

df2 <- df1 %>% select(-c(var2:var3) )  
df2
#        var1
#1 0.75879754
#2 0.31168919
#3 0.03983268

1
อย่าลืมโอกาสอื่น ๆ ที่มาพร้อมกับselect()เช่นcontains()หรือmatches()ที่ยอมรับ regex
ha_pu

23

ความเป็นไปได้อื่น:

df <- df[, setdiff(names(df), c("a", "c"))]

หรือ

df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]

2
น่าเสียดายที่นี่ไม่ได้เพิ่มขึ้นเพราะการใช้setdiffเป็นวิธีที่ดีที่สุดโดยเฉพาะในกรณีที่มีคอลัมน์จำนวนมาก
ctbrown

อีกมุมหนึ่งของเรื่องนี้:df <- df[ , -which(grepl('a|c', names(df)))]
Joe

23
DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
DF

เอาท์พุท:

    x  y z  a
1   1 10 5 11
2   2  9 5 12
3   3  8 5 13
4   4  7 5 14
5   5  6 5 15
6   6  5 5 16
7   7  4 5 17
8   8  3 5 18
9   9  2 5 19
10 10  1 5 20

DF[c("a","x")] <- list(NULL)

เอาท์พุท:

        y z
    1  10 5
    2   9 5
    3   8 5
    4   7 5
    5   6 5
    6   5 5
    7   4 5
    8   3 5    
    9   2 5
    10  1 5

23

โซลูชัน Dplyr

ฉันสงสัยว่าสิ่งนี้จะได้รับความสนใจมากที่นี่ แต่ถ้าคุณมีรายการของคอลัมน์ที่คุณต้องการลบและคุณต้องการทำมันในdplyrสายโซ่ที่ฉันใช้one_of()ในselectข้อ:

นี่คือตัวอย่างง่ายๆที่ทำซ้ำได้:

undesired <- c('mpg', 'cyl', 'hp')

mtcars <- mtcars %>%
  select(-one_of(undesired))

เอกสารสามารถพบได้โดยการเรียกใช้?one_ofหรือที่นี่:

http://genomicsclass.github.io/book/pages/dplyr_tutorial.html


22

จากความสนใจแฟล็กนี้ตั้งค่าหนึ่งในไวยากรณ์ที่ไม่สอดคล้องกันหลายครั้งของ R ตัวอย่างเช่นกำหนดกรอบข้อมูลสองคอลัมน์:

df <- data.frame(x=1, y=2)

สิ่งนี้จะให้กรอบข้อมูล

subset(df, select=-y)

แต่นี่ให้เวกเตอร์

df[,-2]

นี่คือทั้งหมดที่อธิบายไว้ใน?[แต่มันไม่ได้คาดหวังพฤติกรรม อย่างน้อยก็ไม่ให้ฉัน ...


18

นี่คือdplyrวิธีที่จะไปเกี่ยวกับมัน:

#df[ -c(1,3:6, 12) ]  # original
df.cut <- df %>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)  # with dplyr::select()

ฉันชอบสิ่งนี้เพราะสามารถอ่านและทำความเข้าใจได้ง่ายโดยไม่มีคำอธิบายประกอบและมีความทนทานต่อคอลัมน์ที่เปลี่ยนตำแหน่งภายในกรอบข้อมูล นอกจากนี้ยังเป็นไปตามสำนวน vectorized ที่ใช้-ในการลบองค์ประกอบ


การเพิ่มสิ่งนี้ที่ (1) ผู้ใช้ต้องการแทนที่ต้นฉบับ df (2) magrittr มี%<>% โอเปอเรเตอร์เพื่อแทนที่วัตถุอินพุตที่สามารถทำให้ง่ายขึ้นdf %<>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)
Marek

1
หากคุณมีรายการคอลัมน์ที่ยาวที่จะดร็อปด้วยdplyrอาจเป็นการง่ายกว่าที่จะจัดกลุ่มคอลัมน์และวางเพียงหนึ่งลบ:df.cut <- df %>% select(-c(col.to.drop.1, col.to.drop.2, ..., col.to.drop.n))
iNyar

14

ฉันคิดอยู่เสมอว่าจะต้องมีสำนวนที่ดีกว่า แต่สำหรับการลบคอลัมน์ด้วยชื่อฉันมักจะทำสิ่งต่อไปนี้:

df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)

# return everything except a and c
df <- df[,-match(c("a","c"),names(df))]
df

4
ไม่ใช่ความคิดที่ดีที่จะคัดค้านการจับคู่ -df[,-match(c("e","f"),names(df))]
Hadley

. @ JDLong - หากฉันต้องการที่จะลดลงคอลัมน์ที่ชื่อคอลัมน์เริ่มต้นด้วย-?
Chetan Arvind Patil

12

มีฟังก์ชั่นที่เรียกว่าdropNamed()ในBBmiscแพ็คเกจของ Bernd Bischl ที่ทำสิ่งนี้

BBmisc::dropNamed(df, "x")

ข้อดีคือมันหลีกเลี่ยงการทำซ้ำอาร์กิวเมนต์ของ data frame และดังนั้นจึงเหมาะสำหรับการ piping magrittr(เช่นเดียวกับdplyrวิธีการ):

df %>% BBmisc::dropNamed("x")

9

วิธีแก้ไขปัญหาอื่นหากคุณไม่ต้องการใช้ @ hadley ด้านบน: หาก "COLUMN_NAME" เป็นชื่อของคอลัมน์ที่คุณต้องการวาง:

df[,-which(names(df) == "COLUMN_NAME")]

1
(1) ปัญหาคือการวางหลายคอลัมน์พร้อมกัน (2) มันจะไม่ทำงานหากCOLUMN_NAMEไม่ได้อยู่ในdf(ตรวจสอบตัวเองdf<-data.frame(a=1,b=2)) (3) df[,names(df) != "COLUMN_NAME"]ง่ายขึ้นและไม่ต้องทนทุกข์ทรมานจาก (2)
มาเร็ค

คุณสามารถให้ข้อมูลเพิ่มเติมเกี่ยวกับคำตอบนี้ได้ไหม?
Akash Nayak

8

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

library(dplyr)
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 

หากคุณต้องการวางคอลัมน์ที่อาจมีหรือไม่มีอยู่ใน data frame นี่คือการบิดเล็กน้อยโดยใช้select_if()ที่ไม่เหมือนกับการใช้one_of()จะไม่มีการUnknown columns:เตือนหากชื่อคอลัมน์ไม่มีอยู่ ในตัวอย่างนี้ 'bad_column' ไม่ใช่คอลัมน์ใน data frame:

starwars %>% 
  select_if(!names(.) %in% c('height', 'mass', 'bad_column'))

4

ระบุเฟรมข้อมูลและสตริงของชื่อที่คั่นด้วยเครื่องหมายจุลภาคเพื่อลบ:

remove_features <- function(df, features) {
  rem_vec <- unlist(strsplit(features, ', '))
  res <- df[,!(names(df) %in% rem_vec)]
  return(res)
}

การใช้งาน :

remove_features(iris, "Sepal.Length, Petal.Width")

ป้อนคำอธิบายรูปภาพที่นี่


1

whichค้นหาดัชนีของคอลัมน์ที่คุณต้องการที่จะลดการใช้ ให้ดัชนีเหล่านี้เป็นสัญญาณเชิงลบ ( *-1) จากนั้นเซ็ตย่อยของค่าเหล่านั้นซึ่งจะลบออกจาก dataframe นี่คือตัวอย่าง

DF <- data.frame(one=c('a','b'), two=c('c', 'd'), three=c('e', 'f'), four=c('g', 'h'))
DF
#  one two three four
#1   a   d     f    i
#2   b   e     g    j

DF[which(names(DF) %in% c('two','three')) *-1]
#  one four
#1   a    g
#2   b    h

1

หากคุณมีขนาดใหญ่data.frameและมีหน่วยความจำ[ เหลือน้อย . . . หรือrmและwithinจะลบคอลัมน์ของdata.frameตามที่subsetเป็นอยู่ในปัจจุบัน (R 3.6.2) ใช้หน่วยความจำมากขึ้น - ข้างคำใบ้ของคู่มือที่จะใช้subsetการโต้ตอบ

getData <- function() {
  n <- 1e7
  set.seed(7)
  data.frame(a = runif(n), b = runif(n), c = runif(n), d = runif(n))
}

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- DF[setdiff(names(DF), c("a", "c"))] ##
#DF <- DF[!(names(DF) %in% c("a", "c"))] #Alternative
#DF <- DF[-match(c("a","c"),names(DF))]  #Alternative
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- subset(DF, select = -c(a, c)) ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#357 MB are used

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- within(DF, rm(a, c)) ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used

DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF[c("a", "c")]  <- NULL ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.