如何删除数据帧中的行?

我有一个名为“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
1757668 次浏览

关键思想是,你把想要删除的行组成一个集合,并保留这个集合的补项。

在R中,集合的补由'-'操作符给出。

因此,假设data.frame被称为myData:

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

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

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

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

按行号删除的问题

对于快速和肮脏的分析,您可以根据顶部的答案通过数字删除data.frame的行。也就是说,

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

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

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

更好的战略

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

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

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

在数据帧中创建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)

简化顺序:

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) , ]

从员工中删除Dan。data -不需要管理新的data.frame。

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

下面是一个按索引删除一行的快速而简单的函数。

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。任何评论和改进这将是非常欢迎的!

为了完整起见,我将添加这可以用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())。有关更多示例,请参见文档

用名字来识别:

  1. 调用唯一ID并识别数据帧(DF)中的位置。
  2. 标记删除。如果唯一ID应用于多个行,则所有这些行都将被删除。

代码:

Rows<-which(grepl("unique ID", DF$Column))
DF2<-DF[-c(Rows),]
DF2
使用唯一id的另一种方法是对数据进行子集: *这来自于一个实际的报告,我想删除化学标准

Chem.Report<-subset(Chem.Report, Chem_ID!="Standard")

Chem_ID是列名。 !对于排除