ฉันจะลบแถวในกรอบข้อมูลได้อย่างไร


224

ฉันมีกรอบข้อมูลชื่อ "mydata" ที่มีลักษณะเช่นนี้:

   A  B  C   D 
1. 5  4  4   4 
2. 5  4  4   4 
3. 5  4  4   4 
4. 5  4  4   4 
5. 5  4  4   4 
6. 5  4  4   4 
7. 5  4  4   4 

ฉันต้องการลบแถว 2,4,6 ตัวอย่างเช่นนี้:

   A  B  C   D
1. 5  4  4  4 
3. 5  4  4  4 
5. 5  4  4  4 
7. 5  4  4  4 

12
นอกจากนี้คุณอาจต้องการทำความคุ้นเคยกับคำศัพท์ทั่วไปสำหรับการทำงานกับข้อมูล นี้มักจะเรียกว่า Subsetting ซึ่งหากคุณค้นหาใน Google สำหรับ "R กรอบข้อมูลเซต" คุณจะได้รับการที่เป็นประโยชน์มากยูซีแอล R คำถามที่พบบ่อยหน้า ยินดีต้อนรับสู่ Stackoverflow โดยวิธี!
A5C1D2H2I1M1N2O1R2T1

เพิ่มวิธีการย่อยเพิ่มเติมโดยใช้เวกเตอร์บูลีนเพิ่มเติมจากคำตอบที่ยอดเยี่ยมของ @ mrdwab
Paul Hiemstra

2
@ A5C1D2H2I1M1N2O1R2T1: คำถามที่พบบ่อยเกี่ยวกับ UCLA สำหรับการตั้งค่าย่อย R ได้ถูกย้ายแล้ว ตอนนี้ก็ถึงที่นี่
Mike Sherrill 'Cat Recall'

คำตอบ:


340

แนวคิดหลักคือคุณสร้างชุดของแถวที่คุณต้องการลบและเก็บส่วนเสริมของชุดนั้นไว้

ใน R การเติมเต็มชุดจะได้รับจากตัวดำเนินการ '-'

ดังนั้นสมมติว่าdata.frameถูกเรียกว่าmyData:

myData[-c(2, 4, 6), ]   # notice the -

แน่นอนอย่าลืม "กำหนดใหม่" myDataถ้าคุณต้องการที่จะวางแถวเหล่านั้นทั้งหมด --- มิฉะนั้น R เพียงพิมพ์ผลลัพธ์

myData <- myData[-c(2, 4, 6), ]

59
อย่าลืมจดบันทึกที่,นั่นด้วย! ;)
Steven Jeuris

5
จะเกิดอะไรขึ้นถ้า dataframe ของคุณเป็นหนึ่งคอลัมน์ ดูเหมือนว่าจะลดโครงสร้างทั้งหมดและส่งผลเวกเตอร์ของค่า
road_to_quantdom

6
@road_to_quantdom เพิ่มdrop = FALSEในนั่น
A5C1D2H2I1M1N2O1R2T1

4
"ใน R ส่วนประกอบของชุดจะได้รับจากตัวดำเนินการ '-'" -> นี่เป็นถ้อยคำที่ทำให้เข้าใจผิดมาก ดัชนีเชิงลบจะถูกลบออกและนั่นคือมันไม่มีความคิดของส่วนประกอบ หากคุณทำงานกับตรรกะและลองใช้-มันจะไม่ทำงานเพราะผู้ประกอบการที่สมบูรณ์สำหรับ logicals !คือ ส่วนประกอบของ c (2,4,6) ในแถวจะค่อนข้าง setdiff (c (2,4,6), 1: nrow (myData)) ซึ่งไม่ใช่ c (-2, -4, -6) [แม้ว่าทั้งสองจะให้ผลผลิตแถวเดียวกันเมื่อใช้กับ
asac

2
myData[-c(2, 4, 6),,drop=F]@Speldosa, ในความเป็นจริงฉันขอแนะนำให้คุณใส่,drop=Fก่อนการ]เข้าถึงเมทริกซ์เสมอ
Aaron McDaid

82

คุณยังสามารถทำงานกับเวกเตอร์บูลีนที่รู้จักlogicalกันว่า aka :

row_to_keep = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE)
myData = myData[row_to_keep,]

โปรดทราบว่า!ผู้ประกอบการทำหน้าที่เป็นไม่เช่น!TRUE == FALSE:

myData = myData[!row_to_keep,]

ดูเหมือนว่าจะยุ่งยากเล็กน้อยเมื่อเปรียบเทียบกับคำตอบของ @ mrwab (+1 btw :)) แต่เวกเตอร์เชิงตรรกะสามารถสร้างขึ้นได้ทันทีเช่นที่ค่าคอลัมน์เกินค่าที่แน่นอน:

myData = myData[myData$A > 4,]
myData = myData[!myData$A > 4,] # equal to myData[myData$A <= 4,]

คุณสามารถแปลงเวกเตอร์บูลีนเป็นเวกเตอร์ของดัชนี:

row_to_keep = which(myData$A > 4)

ในที่สุดกลอุบายที่ประณีตมาก ๆ ก็คือคุณสามารถใช้การย่อยแบบนี้ไม่เพียง แต่สำหรับการแยกเท่านั้น แต่ยังสำหรับการมอบหมาย:

myData$A[myData$A > 4,] <- NA

โดยที่คอลัมน์AถูกกำหนดNA(ไม่ใช่ตัวเลข) โดยที่Aเกินกว่า 4


ถ้าคุณต้องการที่จะแยกพวกเขา? ในตัวอย่างหมายเลข 3 ของคุณถ้าคุณจางหาย
GabrielMontenegro

61

ปัญหาในการลบตามหมายเลขแถว

สำหรับการวิเคราะห์ที่รวดเร็วและสกปรกคุณสามารถลบแถวของ data.frame โดยตัวเลขตามคำตอบด้านบน กล่าวคือ

newdata <- myData[-c(2, 4, 6), ] 

อย่างไรก็ตามหากคุณพยายามเขียนสคริปต์การวิเคราะห์ข้อมูลที่มีประสิทธิภาพคุณควรหลีกเลี่ยงการลบแถวด้วยตำแหน่งที่เป็นตัวเลข นี่เป็นเพราะลำดับของแถวในข้อมูลของคุณอาจมีการเปลี่ยนแปลงในอนาคต หลักการทั่วไปของ data.frame หรือตารางฐานข้อมูลคือลำดับของแถวไม่ควรสำคัญ หากคำสั่งมีความสำคัญควรทำการเข้ารหัสในตัวแปรจริงใน data.frame

ตัวอย่างเช่นสมมติว่าคุณนำเข้าชุดข้อมูลและลบแถวตามตำแหน่งที่เป็นตัวเลขหลังจากตรวจสอบข้อมูลและระบุหมายเลขแถวของแถวที่คุณต้องการลบ อย่างไรก็ตามในภายหลังคุณจะได้รับข้อมูลดิบและดูข้อมูลใหม่อีกครั้ง รหัสการลบแถวของคุณจะลบแถวที่ไม่ถูกต้องและแย่กว่านั้นคือคุณไม่น่าจะได้รับข้อผิดพลาดใด ๆ ที่เตือนคุณว่าสิ่งนี้เกิดขึ้น

กลยุทธ์ที่ดีกว่า

กลยุทธ์ที่ดีกว่าคือการลบแถวตามคุณสมบัติที่สำคัญและมีเสถียรภาพของแถว ตัวอย่างเช่นหากคุณมีidตัวแปรคอลัมน์ที่ระบุแต่ละกรณีโดยเฉพาะคุณสามารถใช้สิ่งนั้นได้

newdata <- myData[ !(myData$id %in% c(2,4,6)), ]

ในบางครั้งคุณจะมีเกณฑ์การยกเว้นอย่างเป็นทางการที่สามารถระบุได้และคุณสามารถใช้หนึ่งในเครื่องมือการตั้งค่าย่อยจำนวนมากใน R เพื่อแยกกรณีและปัญหาตามกฎนั้น


11

สร้างคอลัมน์ id ใน data frame ของคุณหรือใช้ชื่อคอลัมน์ใด ๆ เพื่อระบุแถว การใช้ดัชนีไม่ยุติธรรมที่จะลบ

ใช้subsetฟังก์ชั่นเพื่อสร้างเฟรมใหม่

updated_myData <- subset(myData, id!= 6)
print (updated_myData)

updated_myData <- subset(myData, id %in% c(1, 3, 5, 7))
print (updated_myData)

9

ตามลำดับที่ง่ายขึ้น:

mydata[-(1:3 * 2), ]

ตามลำดับ:

mydata[seq(1, nrow(mydata), by = 2) , ]

ตามลำดับเชิงลบ:

mydata[-seq(2, nrow(mydata), by = 2) , ]

หรือถ้าคุณต้องการเซ็ตย่อยโดยเลือกตัวเลขคี่:

mydata[which(1:nrow(mydata) %% 2 == 1) , ]

หรือถ้าคุณต้องการเซ็ตย่อยโดยเลือกตัวเลขคี่รุ่น 2:

mydata[which(1:nrow(mydata) %% 2 != 0) , ]

หรือถ้าคุณต้องการเซ็ตย่อยโดยการกรองตัวเลขออก:

mydata[!which(1:nrow(mydata) %% 2 == 0) , ]

หรือถ้าคุณต้องการเซ็ตย่อยโดยการกรองเลขคู่ให้เป็นรุ่น 2:

mydata[!which(1:nrow(mydata) %% 2 != 1) , ]

5

ลบ Dan จาก employee.data - ไม่จำเป็นต้องจัดการ data.frame ใหม่

employee.data <- subset(employee.data, name!="Dan")

0

นี่คือฟังก์ชั่นที่รวดเร็วและสกปรกในการลบแถวโดยดัชนี

removeRowByIndex <- function(x, row_index) {
  nr <- nrow(x)
  if (nr < row_index) {
    print('row_index exceeds number of rows')
  } else if (row_index == 1)
  {
    return(x[2:nr, ])
  } else if (row_index == nr) {
    return(x[1:(nr - 1), ])
  } else {
    return (x[c(1:(row_index - 1), (row_index + 1):nr), ])
  }
}

ข้อบกพร่องหลักคือมันคืออาร์กิวเมนต์ row_index ไม่เป็นไปตามรูปแบบ R ของการเป็นเวกเตอร์ของค่า อาจมีปัญหาอื่น ๆ เนื่องจากฉันใช้เวลาสองสามนาทีในการเขียนและทดสอบและเพิ่งเริ่มใช้ R ในไม่กี่สัปดาห์ที่ผ่านมา ความคิดเห็นและการปรับปรุงใด ๆ เกี่ยวกับเรื่องนี้จะยินดีมาก!


0

เพื่อความสมบูรณ์ฉันจะเพิ่มที่ว่านี้สามารถทำได้ด้วยเช่นกันโดยใช้dplyr sliceข้อดีของการใช้สิ่งนี้คือมันสามารถเป็นส่วนหนึ่งของเวิร์กโฟลว์ที่ถูกวางท่อได้

df <- df %>%
  .
  .
  slice(-c(2, 4, 6)) %>%
  .
  .

แน่นอนคุณสามารถใช้งานได้โดยไม่ต้องใช้ท่อ

df <- slice(df, -c(2, 4, 6))

รูปแบบ "ไม่เวกเตอร์" -c(2, 4, 6)วิธีการที่จะได้รับทุกอย่างที่เป็นไม่ได้ที่แถว 2, 4 และ 6 ตัวอย่างโดยใช้ช่วงสมมติว่าคุณต้องการที่จะลบ 5 slice(df, 6:n())แถวแรกที่คุณสามารถทำได้ สำหรับตัวอย่างเพิ่มเติมโปรดดูที่เอกสาร

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