从数据框中删除特定行

8

我正在处理一些美国政府数据,其中包含大量城市和邮政编码。

经过一些处理后,数据的格式如下所示。

dat1 = data.frame(keyword=c("Bremen", "Brent", "Centreville, AL", "Chelsea, AL", "Bailytown, Alabama", "Calera, Alabama",
              "54023", "54024"), tag=c(rep("AlabamCity",2), rep("AlabamaCityST",2), rep("AlabamaCityState",2), rep("AlabamaZipCode",2)))
dat1

然而,有一些关键词无法正确工作。因此,在下面的示例中,有两个“邮政编码”,分别标记为“AlabamaCity”和“AlabamaCityState”。由于某种原因,政府的原始数据集有几个邮政编码未能与其他邮政编码正确分组。

dat2 = data.frame(keyword=c("Bremen", "Brent", "50143", "Chelsea, AL", "Bailytown, Alabama", "52348",
              "54023", "54024"), tag=c(rep("AlabamCity",2), rep("AlabamaCityST",2), rep("AlabamaCityState",2), rep("AlabamaZipCode",2)))
dat2

我想知道如何遍历整个关键字列表,并删除所有具有数值的行(实际上它们被保存为字符值),这些行没有“AlabamaZipCode”标记。因此,先前的数据应该看起来像这样。
dat3 = data.frame(keyword=c("Bremen", "Brent", "Chelsea, AL", "Bailytown, Alabama", "54023", "54024"), 
          tag=c(rep("AlabamCity",2), rep("AlabamaCityST",1), rep("AlabamaCityState",1), rep("AlabamaZipCode",2)))
dat3

挑战似乎是我想保留某些数字值,而删除其他数字值。 有人能帮忙吗?

3个回答

15

我认为两个grepl表达式可以解决问题:

> dat2[ !( grepl("City", dat2$tag) &  grepl("^\\d", dat2$keyword) ) , ]
             keyword              tag
1             Bremen       AlabamCity
2              Brent       AlabamCity
4        Chelsea, AL    AlabamaCityST
5 Bailytown, Alabama AlabamaCityState
7              54023   AlabamaZipCode
8              54024   AlabamaZipCode

你正在删除在tag中包含"City"且在keyword中存在数字的行。


6

将数据存储为字符而不是因子有助于提高效率:

dat2 <- data.frame(keyword=c("Bremen", "Brent", "50143", "Chelsea, AL", 
                             "Bailytown, Alabama", "52348", "54023", "54024"),   
                   tag=c(rep("AlabamCity",2), rep("AlabamaCityST",2), 
                         rep("AlabamaCityState",2), rep("AlabamaZipCode",2)),
                   stringsAsFactors = FALSE) ## note this bit

现在我们可以将关键字转换为数字,如果它不是字符格式的数字,则会得到一个NA
want <- with(dat2, as.numeric(keyword))

这给了我们这个结果:
> (want <- with(dat2, as.numeric(keyword)))
[1]    NA    NA 50143    NA    NA 52348 54023 54024
Warning message:
In eval(expr, envir, enclos) : NAs introduced by coercion

您可以忽略警告或抑制它,但不要随意使用它,因为它可能掩盖问题:

suppressWarnings(want <- with(dat2, as.numeric(keyword)))

最后一步是选择元素want中不是NAkeyword等于"AlabamaZipCode"的内容,我们使用&来实现此操作。
(!is.na(want) & (dat2$tag != "AlabamaZipCode"))

这选择了我们不想要的行,因此我们需要对上面的内容取反,将TRUE变为FALSE,反之亦然:

!(!is.na(want) & (dat2$tag != "AlabamaZipCode"))

把这些内容放在一起,我们有:
dat2[!(!is.na(want) & (dat2$tag != "AlabamaZipCode")), ]

这将会给出:

> dat2[!(!is.na(want) & (dat2$tag != "AlabamaZipCode")), ]
             keyword              tag
1             Bremen       AlabamCity
2              Brent       AlabamCity
4        Chelsea, AL    AlabamaCityST
5 Bailytown, Alabama AlabamaCityState
7              54023   AlabamaZipCode
8              54024   AlabamaZipCode

完整的解决方案是:

want <- with(dat2, as.numeric(keyword))
dat2[!(!is.na(want) & (dat2$tag != "AlabamaZipCode")), ]

3
这里有一种(略微复杂的)方法,您可以考虑。首先,为每行创建一个身份列。这将有助于子集处理。其次,创建一个与您的条件匹配的id向量。最后,将这些id从最终数据中子集出来。
您发布的数据默认为因子,而不是字符数据,因此我已经做了相应的调整。如果实际数据与此不同,您需要相应地进行调整。另外,当我将数据转换为数字时,会生成NA。会产生警告消息,但我们可以忽略这个问题。
#Generate an ID column
dat4$id <- 1:nrow(dat4)

#Create a vector of the id's that match your criteria'
outliers <- dat4[as.character(dat4$tag) != "AlabamaZipCode" & !(is.na(as.numeric(as.character(dat4$keyword)))) , "id"]

subset(dat4, !(id %in% outliers), select = 1:2)
             keyword              tag
1             Bremen       AlabamCity
2              Brent       AlabamCity
4        Chelsea, AL    AlabamaCityST
5 Bailytown, Alabama AlabamaCityState
7              54023   AlabamaZipCode
8              54024   AlabamaZipCode

实际上,你可以将所有内容缩短为以下内容,并避免生成id。
dat4[!(as.character(dat4$tag) != "AlabamaZipCode" & !(is.na(as.numeric(as.character(dat4$keyword))))) , ]

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