我正在处理一些美国政府数据,这些数据包含很长的城市和邮政编码列表。 完成一些工作后,数据采用以下格式。
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'。出于某种原因,政府的原始数据集有几个zipcodes 没有与其他邮政编码正确分组。
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
挑战似乎是我想要保留某些数值以及我想要删除的其他数值。 任何人都可以提供帮助。
答案 0 :(得分:10)
我认为两个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
您正在keyword
tag
和“城市”中有数字的行
答案 1 :(得分:5)
它有助于将数据存储为字符,而不是因素:
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
现在我们可以将keyword
转换为数字,如果它不是字符格式的数字,我们会得到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)))
最后一步是选择{{1>} want
和 NA
等于{{{{}}的元素1}},我们使用keyword
执行:
"AlabamaZipCode"
选择我们不想要的行,因此我们需要否定上述内容,将&
转为(!is.na(want) & (dat2$tag != "AlabamaZipCode"))
,反之亦然:
TRUE
把这些放在一起我们有:
FALSE
给出:
!(!is.na(want) & (dat2$tag != "AlabamaZipCode"))
完整的解决方案是:
dat2[!(!is.na(want) & (dat2$tag != "AlabamaZipCode")), ]
答案 2 :(得分:2)
这是您可以考虑的一种(略微复杂的)方法。首先,为每行创建一个标识列。这将有助于子集化。其次,创建符合条件的那些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))))) , ]