从R数据框中删除行

22

我有以下数据框:

> str(df)
'data.frame':   3149 obs. of  9 variables:
 $ mkod : int  5029 5035 5036 5042 5048 5050 5065 5071 5072 5075 ...
 $ mad  : Factor w/ 65 levels "Akgün Kasetçilik         ",..: 58 29 59 40 56 11 33 34 19 20 ...
 $ yad  : Factor w/ 44 levels "BAKUGAN","BARBIE",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ donem: int  201101 201101 201101 201101 201101 201101 201101 201101 201101 201101 ...
 $ sayi : int  201101 201101 201101 201101 201101 201101 201101 201101 201101 201101 ...
 $ plan : int  2 2 3 2 2 2 7 3 2 7 ...
 $ sevk : int  2 2 3 2 2 2 6 3 2 7 ...
 $ iade : int  0 0 3 1 2 2 6 2 2 3 ...
 $ satis: int  2 2 0 1 0 0 0 1 0 4 ...

我想从这个数据框中删除21个特定的行。

> a <- df[df$plan==0 & df$sevk==0,]
> nrow(a)
[1] 21

当我删除那21行时,我将会得到一个新的数据框,其行数为3149 - 21 = 3128。我找到以下解决方案:

> b <- df[df$plan!=0 | df$sevk!=0,]
> nrow(b)
[1] 3128

我的解决方案使用了一种修改后的逻辑表达式(!=代替==|代替&)。除了修改原始的逻辑表达式之外,我如何获得没有这21行的新数据框?我需要类似这样的东西:

> df[-a,] #does not work

编辑(特别是针对那些点踩的人,我希望他们能明白为什么我需要另一种解决方案):我之所以要求另一种解决方案,是因为我正在编写一段很长的代码,并且在代码的不同部分有各种变量赋值(例如我的示例中的a)。因此,当我需要删除代码前进部分中的行时,我不想回去尝试编写 a-like 表达式内部逻辑表达式的反面。这就是为什么对我来说 df[-a,] 更加可用的原因。


-1 你已经在问题中提供了解决方案。目前的问题没有需要解决的问题。 - Richie Cotton
1
@RichieCotton:我的解决方案使用了一个修改过的(不同的)逻辑表达式,最终得到了我需要的结果;但是我想看到的是如何从数据框中删除特定行。我在问题中包含了我的解决方案,因为我不想在答案中看到它。 - Mehper C. Palavuzlar
我在我的问题中添加了几行文字来解释我想要知道的内容。 - Mehper C. Palavuzlar
我认为有些混淆,不清楚为什么你想要像 df[-a,] 这样的东西,当 df[df$plan!=0 | df$sevk!=0,] 似乎是正确的方法。你能否解释一下,在更大的背景下,为什么像 df[-a,] 这样的方法更可取?也许在更大的背景下,有一种方法可以避免这个问题。 - jthetzel
这是因为我正在编写一段长代码,并且在代码的各个部分有各种变量赋值(例如我的示例中的 a)。因此,当我需要在代码的前进部分删除行时,我不想回去尝试编写 a-like 表达式内逻辑表达式的反义词。这就是为什么 df[-a,] 对我来说更可用的原因。 - Mehper C. Palavuzlar
5个回答

15
只需要将您的逻辑下标取反即可:
a <- df[!(df$plan==0 & df$sevk==0),]

12

您可以使用rownames指定一个“补充”的数据框。如果它们是数字行名称,则更容易:

df[-as.numeric(rownames(a)),]

但更普遍地,您可以使用:

df[setdiff(rownames(df),rownames(a)),]

当然,这假设您有行名称,这在此情况下OP确实如此,但这不是一般解决方案。 - Carl Witthoft

9
你在寻找 subset() 函数吗?
dat <- airquality
dat.sub <- subset(dat, Temp > 80 & Month < 10)

dim(dat)
dim(dat.sub)

应用于您的示例:
df.sub <- subset(df, plan != 0 & sevk != 0)

这与我的解决方案相同:df[df$plan!=0 | df$sevk!=0,],它选择了一个子集;但还是谢谢。 - Mehper C. Palavuzlar
顺便提一下,在 subset(df, plan != 0 & sevk != 0) 中,& 运算符必须替换为 |(或)运算符。 - Mehper C. Palavuzlar

2

您已经接近成功了。'a'需要是一个索引向量:

    df <- data.frame(plan=runif(10),sevk=runif(10))
    a <- c(df$plan<.1 | df$sevk < .1) # some logical thing
    df[-a,]

或者,使用您的数据:
    a <- c(df$plan==0 & df$sevk==0)
    df[-a,]

我用我的数据尝试了你代码的最后两行,但是结果不对(3148行而不是3128行)。顺便说一下,b[-a,] 应该改为 df[-a,] - Mehper C. Palavuzlar
抱歉,我的代码在上面的自包含小例子中可以运行,所以我猜你的数据出了问题,超出了我的能力范围。 - tim riffe

0

我不明白为什么你反对你的解决方案,但这里有另一种方法。

which( df[df$plan==0 & df$sevk==0,], arr.ind=TRUE) ->killlist 
newdf <- df[-c(killlist[1,])] 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接