280

我有一个名为“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 
4

8 回答 8

418

关键思想是您形成一组要删除的行,并保留该组的补码。

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

所以,假设data.frame被称为myData

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

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

myData <- myData[-c(2, 4, 6), ]
于 2012-09-08T04:39:37.100 回答
99

您还可以使用所谓的布尔向量,也就是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。

于 2012-09-08T10:57:18.140 回答
78

按行号删除的问题

对于快速和肮脏的分析,您可以根据最佳答案按数字删除 data.frame 的行。IE,

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

但是,如果您尝试编写一个健壮的数据分析脚本,您通常应该避免按数字位置删除行。这是因为您的数据中的行顺序将来可能会发生变化。data.frame 或数据库表的一般原则是行的顺序无关紧要。如果顺序确实很重要,则应将其编码在 data.frame 中的实际变量中。

例如,假设您在检查数据并确定要删除的行的行号后导入数据集并按数字位置删除行。但是,稍后,您会进入原始数据并查看并重新排序数据。您的行删除代码现在将删除错误的行,更糟糕的是,您不太可能收到任何警告您已发生这种情况的错误。

更好的策略

更好的策略是根据行的实质性和稳定属性删除行。例如,如果您有一个id唯一标识每个案例的列变量,您可以使用它。

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

其他时候,您将有一个可以指定的正式排除标准,并且您可以使用 R 中的许多子集工具之一来根据该规则排除案例。

于 2017-05-15T05:51:34.367 回答
15

在数据框中创建 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)
于 2017-08-09T11:54:34.977 回答
12

按简化顺序:

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) , ]
于 2018-09-06T08:31:51.497 回答
8

为了完整起见,我将补充一点,这也可以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()). 有关更多示例,请参阅文档

于 2020-04-20T23:50:37.440 回答
6

从 employee.data 中删除 Dan - 无需管理新的 data.frame。

employee.data <- subset(employee.data, name!="Dan")
于 2019-01-30T01:27:54.580 回答
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。非常欢迎对此提出任何意见和改进!

于 2019-02-24T08:46:37.703 回答