按%ONE或更多指定列中的特定值%过滤行

时间:2014-11-05 19:52:07

标签: r

我有大量以" country"开头的数据框列。并以数字方式加1(例如country1country2country3)。我想将dplyr filter我的数据框df用于 ONE OR MORE 变量包含某些国家/地区名称作为值的行(即{{1} }}"),以及许多其他条件。

我已经尝试使用country1 OR country2 OR country3 %in% "Brazil来执行此操作,但我遇到的问题是该函数与grep函数的其余部分同时进行评估,因此我得到了一个错误信息。以下是我尝试过的内容:

filter

当然,R只是将df1 <- filter(df, a %in% value1 & b %in% value2 & grep("^country.*", colnames(df), value = TRUE) %in% c("Brazil") 函数评估为...

grep

并返回一个逻辑向量,其中显然没有值==&#34;巴西&#34;:

& c("country1", "country2", "country3", ... ) %in% c("Brazil")

有没有办法在不费力地输入所有变量的情况下做到这一点?例如......

[1] FALSE FALSE FALSE ... ...

谢谢!

5 个答案:

答案 0 :(得分:5)

更紧凑的版本:

df %>% filter(str_detect(country1:country3, "Brazil"))
#  country1 country2 country3
#         1        A        B   Brazil

(需要stringr以及dplyr

根据@ beginneR的评论,这也可能有用:

df %>% filter(str_detect(starts_with("country"), "Brazil"))

答案 1 :(得分:4)

这是使用碱基R

的载体化溶液
dat[rowSums(dat[grepl("^country\\d+$", names(dat))] == "Brazil") > 0, ]
##   Random1 Random2 country1 country2 country3
## 1       C       D        A        B   Brazil

data.table二进制搜索(对于大数据集来说将是某个赢家)

library(data.table)
setDT(dat)[, indx := rowSums(.SD[, grepl("^country\\d+$", names(dat)), with = F] == "Brazil") > 0]
setkey(dat, indx)[J(TRUE)]
##    Random1 Random2 country1 country2 country3 indx
## 1:       C       D        A        B   Brazil TRUE

数据集

dat <- data.frame(Random1 = c("C", "Brazil"), Random2 = "D", 
                  country1 = "A", country2 = "B", country3 = c("Brazil", "C"))
#   Random1 Random2 country1 country2 country3
# 1       C       D        A        B   Brazil
# 2  Brazil       D        A        B        C 

答案 2 :(得分:3)

您也可以尝试这样的事情。我首先创建一个行的索引,其中“Brazil”出现在任何“country”列中,然后使用索引来对数据进行子集化/过滤:

indx <- df %>% select(starts_with("country")) %>% 
             mutate_each(funs(grepl("Brazil", .))) %>% 
             rowSums > 0
indx
#[1]  TRUE FALSE

df %>% filter(indx)
#  country1 country2 country3
#1        A        B   Brazil

样本数据:

df <- data.frame(country1 = "A", country2 = "B", country3 = c("Brazil", "C"))
df
#  country1 country2 country3
#1        A        B   Brazil
#2        A        B        C

修改

如果您想查找多个国家/地区名称,只需稍加修改即可将感兴趣的国家/地区名称粘贴在一起,例如:像这样:

首先,我会略微修改示例数据,以包含第三行“Argentina”。

df <- data.frame(country1 = "A", country2 = "B", country3 = c("Brazil", "C", "Argentina"))
df
#  country1 country2  country3
#1        A        B    Brazil
#2        A        B         C
#3        A        B Argentina

然后,您可以在向量中存储要查找的国家/地区名称:

x  <- c("Brazil", "Argentina", "USA")

现在,再次构建indx,但将“x”的国家/地区名称粘贴在一起,以便grepl查找其中任何一个(技巧是以“|”折叠 - 逻辑OR):

indx <- df %>% select(starts_with("country")) %>% 
  mutate_each(funs(grepl(paste(x, collapse = "|"), .))) %>% 
  rowSums > 0

现在,您可以采用标准方式对数据进行子集化,例如使用dplyr:

df[indx,]
#  country1 country2  country3
#1        A        B    Brazil
#3        A        B Argentina
df %>% filter(indx)
#  country1 country2  country3
#1        A        B    Brazil
#2        A        B Argentina

答案 3 :(得分:1)

您可以使用逻辑矩阵作为帮助程序并获取唯一行

dat[sort(unique(row(dat)[dat == "Brazil"])),]
#   country1 country2  country3 country4  country5
# 3   Brazil   Brazil Argentina   Brazil    Brazil
# 4   Mexico    Chile    Brazil    Chile Argentina
# 5   Brazil    Chile Argentina   Brazil Argentina
# 6   Mexico    Chile Argentina   Brazil    Brazil

另外,您可以使用which

w <- which(dat == "Brazil", arr.ind=TRUE)[,"row"]
dat[sort(unique(w)),]

dat数据的位置为:

set.seed(25)
country <- c("Brazil", "Chile", "Argentina", "Mexico")
dat <- as.data.frame(matrix(sample(country, 30, TRUE), 6))
dat <- setNames(dat, paste0("country", 1:ncol(dat)))

答案 4 :(得分:0)

您可以将列粘贴在一起以获得超级列,然后将其grep用于巴西吗?

示例:

set.seed(1)
dat <- data.frame(matrix(sample(c(rep('Canada',10), 'Brazil'), 20, replace=T),
                         ncol=5),
                  stringsAsFactors=F)

> dat
      X1     X2     X3     X4     X5
1 Canada Canada Canada Canada Canada
2 Canada Canada Canada Canada Brazil
3 Canada Brazil Canada Canada Canada
4 Canada Canada Canada Canada Canada

然后:

dat$X6 <- apply(dat, 1, paste, collapse="")
grepl('Brazil', dat$X6)

> grepl('Brazil', dat$X6)
[1] FALSE  TRUE  TRUE FALSE

正如预期的那样,仅对其中包含巴西的行(即2和3)返回TRUE