如何删除数据框中的行?


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
此外,您可能想熟悉一些处理数据的常用术语。这通常称为子集,如果您在Google中搜索“ r子集数据框”,则将进入非常有用的UCLA R FAQ页面。欢迎来到Stackoverflow!
A5C1D2H2I1M1N2O1R2T1'9年

除了@mrdwab的出色答案之外,还添加了一些其他使用布尔向量进行子集的方法。
Paul Hiemstra 2012年

2
@ A5C1D2H2I1M1N2O1R2T1:R子集的UCLA常见问题解答已移动。现在在这里
Mike Sherrill'Cat Recall'17

Answers:


340

关键思想是形成要删除的行的集合,并保留该集合的补充。

在R中,集合的补码由'-'运算符给出。

因此,假设data.frame称为myData

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

当然,myData如果您想完全删除那些行,请不要忘记“重新分配” -否则,R只会打印结果。

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

59
别忘了,在里面注意!;)
Steven Jeuris 2015年

5
如果您的数据框只有一列怎么办。似乎删除了整个结构并输出了值的向量
road_to_quantdom 2015年

6
@road_to_quantdom,drop = FALSE在其中添加一个。
A5C1D2H2I1M1N2O1R2T1 2015年

4
“在R中,集合的补码由'-'运算符给出”->这是一个非常令人误解的措辞。负索引被删除,仅此而已,没有补码的概念。如果您使用逻辑并尝试使用-它将不起作用,因为逻辑的补数运算符为!。行中c(2,4,6)的补码应为setdiff(c(2,4,6),1:nrow(myData)),而不是c(-2,-4,-6) ,尽管当与一起使用时,两者都会产生相同的行[
asac 2015年

2
@Speldosa , myData[-c(2, 4, 6),,drop=F]。事实上,我建议你总是插入,drop=F之前只是]在任何矩阵访问。
亚伦·麦克戴德

82

您也可以使用所谓的布尔向量aka logical

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

请注意,!运算符充当NOT,即!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列,或使用任何列名来标识该行。使用索引删除不公平。

使用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

从employee.data中删除Dan-无需管理新的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())。有关更多示例,请参阅docs

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.