R 删除数据帧行的简单方法对没有行与删除条件匹配的实例具有很强的鲁棒性
R中数据操作的一个常见任务是通过删除符合特定条件的行来对数据帧进行子集划分。然而,在R中这样做的简单方法在逻辑上似乎不一致,甚至对没有经验的人(比如我自己)来说是危险的 假设我们有一个数据帧,我们希望排除属于“G1”处理的行:R 删除数据帧行的简单方法对没有行与删除条件匹配的实例具有很强的鲁棒性,r,R,R中数据操作的一个常见任务是通过删除符合特定条件的行来对数据帧进行子集划分。然而,在R中这样做的简单方法在逻辑上似乎不一致,甚至对没有经验的人(比如我自己)来说是危险的 假设我们有一个数据帧,我们希望排除属于“G1”处理的行: Treatment=c("G1","G1","G1","G1","G1","G1","G2","G2","G2","G2","G2", "G2","G3","G3","G3","G3","G3","G3") Vals=c(runif(6),runif(6)+0.9,run
Treatment=c("G1","G1","G1","G1","G1","G1","G2","G2","G2","G2","G2",
"G2","G3","G3","G3","G3","G3","G3")
Vals=c(runif(6),runif(6)+0.9,runif(6)-0.3)
data=data.frame(Treatment)
data=cbind(data, Vals)
正如预期的那样,下面的代码删除了与第一行的条件匹配的数据帧行
to_del=which(data$Treatment=="G1")
new_data=data[-to_del,]
new_data
但是,与预期相反,如果“which”命令找不到任何匹配行,则使用此方法,此代码将删除所有行,而不是单独保留它们
to_del=which(data$Treatment=="G4")
new_data=data[-to_del,]
new_data
上面的代码导致数据框中没有剩余行,这毫无意义(即,由于R没有找到与我的删除条件匹配的行,所以它删除了所有行)。我的变通工作可以完成这项工作,但我可以想象,如果没有所有这些条件语句,有一种更简单的方法可以完成这项工作
###WORKAROUND
to_del=which(data$Treatment=="G4") #no G4 treatment in this particular data frame
if (length(to_del)>0){
new_data=data[-to_del,]
}else{
new_data=data
}
new_data
是否有人有一种简单的方法可以做到这一点,即使没有行符合指定的条件也可以做到 您无意中发现了一个使用
的常见问题,即。使用=代码>取而代之
new_data <- data[data$Treatment!="G4",]
如果您按NA
进行子集划分,也会遇到问题:
R> # subsetting by NA
R> (1:3)[NA]
[1] NA NA NA
问题在于,您不是在选择要删除的行,而是在选择要保留的行。正如您所发现的,您可以经常交换这些概念,但有时会出现问题
具体地说,当您使用which
时,您会问R“这个向量的哪些元素是真的”。但是,当它找不到时,它通过返回整数(0)
来指示这一点
整数(0)不是实际数,因此取整数(0)的负数仍然会得到整数(0)
但是,如果您打算简单地使用它进行过滤,则不需要使用它
相反,将要传递给的语句作为过滤器直接传递给数据[…]
。回想一下,您可以使用逻辑向量作为索引,也可以使用整数向量 为什么不使用子集
subset(data, ! rownames(data) %in% to_del )
(无论如何,您在数据[-to_del,]
示例中隐式匹配了行名。)
当然,一旦成功了,你就可以继续使用“[”
我喜欢使用data.table
进行子集设置,因为它更直观、更短,并且在使用大数据集时运行更快
library(data.table)
data.dt<-as.data.table(data)
setkey(data.dt, Treatment)
data.dt[!"G1",]
## Treatment Vals
## 1: G2 0.90264622
## 2: G2 1.47842130
## 3: G2 1.52494735
## 4: G2 1.46373958
## 5: G2 1.12850658
## 6: G2 1.46705561
## 7: G3 0.58451869
## 8: G3 -0.20231228
## 9: G3 0.52519475
## 10: G3 0.62956475
## 11: G3 -0.06655426
## 12: G3 0.56814703
data.dt[!"G4",]
## Treatment Vals
## 1 G1 0.93411692
## 2 G1 0.60153972
## 3 G1 0.28147464
## 4 G1 0.97264924
## 5 G1 0.50804831
## 6 G1 0.48273876
## 7 G2 0.90264622
## 8 G2 1.47842130
## 9 G2 1.52494735
## 10 G2 1.46373958
## 11 G2 1.12850658
## 12 G2 1.46705561
## 13 G3 0.58451869
## 14 G3 -0.20231228
## 15 G3 0.52519475
## 16 G3 0.62956475
## 17 G3 -0.06655426
## 18 G3 0.56814703
库(data.table)
data.dt+1:被巧妙的尝试所打动。感谢你简单而快速的回答。Joshua和Ricardo建议的两种方法都很有效:new_data=data[data$Treatment!=“G4”,]new_data=data[!data$Treatment==“G4”,]那么当逻辑向量中缺少值时呢?在这种情况下,我使用它来防止奇数behvaior。@Aaron,这在这种情况下很有帮助。但实际上,您只需将一个“奇数”行为替换为另一个。如果目标是避免意外行为,我建议更明确地处理它,例如x[is.na(x)]那么,如果!=
返回一个NA
,有什么建议吗?(我问这个问题是因为我用了哪个,幸运的是我从来没有遇到过OP的问题,尽管现在我担心有一天可能会……。@Aaron:只有当结果包含一个NA
,这才是一个问题。这仍然有效:(1:3)[c(真,不,假)]#[1]1不
。我想我通常只想要那些真的
,而不是不
。也许我然后就把不
设置为假
?好了
data[ ! rownames(data) %in% to_del , ]
library(data.table)
data.dt<-as.data.table(data)
setkey(data.dt, Treatment)
data.dt[!"G1",]
## Treatment Vals
## 1: G2 0.90264622
## 2: G2 1.47842130
## 3: G2 1.52494735
## 4: G2 1.46373958
## 5: G2 1.12850658
## 6: G2 1.46705561
## 7: G3 0.58451869
## 8: G3 -0.20231228
## 9: G3 0.52519475
## 10: G3 0.62956475
## 11: G3 -0.06655426
## 12: G3 0.56814703
data.dt[!"G4",]
## Treatment Vals
## 1 G1 0.93411692
## 2 G1 0.60153972
## 3 G1 0.28147464
## 4 G1 0.97264924
## 5 G1 0.50804831
## 6 G1 0.48273876
## 7 G2 0.90264622
## 8 G2 1.47842130
## 9 G2 1.52494735
## 10 G2 1.46373958
## 11 G2 1.12850658
## 12 G2 1.46705561
## 13 G3 0.58451869
## 14 G3 -0.20231228
## 15 G3 0.52519475
## 16 G3 0.62956475
## 17 G3 -0.06655426
## 18 G3 0.56814703