如果任何列包含特定字符串,则删除该行

14

我正在尝试找出在R中删除包含特定字符串的行的最佳方法,在我的情况下是“no_data”。

我有来自外部来源的数据,将na替换为“no_data”。

一个示例是这样的:

 time  |speed  |wheels
1:00   |30     |no_data
2:00   |no_data|18
no_data|no_data|no_data
3:00   |50     |18

我想浏览数据并删除包含任何列中的'no_data'字符串的每一行。 我在弄清楚这个问题方面遇到了很多麻烦。 我尝试过sapply,filter,grep以及这三种方法的组合。 我绝不是r专家,所以可能只是我在使用时出错了。 任何帮助都将不胜感激。


相关 https://dev59.com/oWAh5IYBdhLWcg3wE_1P#49858451 - tjebo
1
这个回答解决了你的问题吗?过滤包含特定字符串的行 - tjebo
4个回答

11

我们可以使用 rowSums 来创建一个逻辑型的 vector 并基于它进行子集筛选。

df1[rowSums(df1 == "no_data")==0, , drop = FALSE]
#   time speed wheels
#4 3:00    50     18

数据

df1 <- structure(list(time = c("1:00", "2:00", "no_data", "3:00"), speed = c("30", 
"no_data", "no_data", "50"), wheels = c("no_data", "18", "no_data", 
"18")), .Names = c("time", "speed", "wheels"), class = "data.frame", 
row.names = c(NA, -4L))

当我执行 df1 == 'no_data' 时,得到了一些奇怪的结果。你是从 OP 读取数据帧还是自己创建的? - Sotos
1
@Sotos 更新了我使用的数据。 - akrun
当我尝试使用这种方法时,出现了“字符串不符合标准的明确格式”的错误提示。我猜测这是因为在真实数据集中,我混合使用了字符、整数和数字变量。我没有在示例中表达清楚... - lentz
1
@lentz,您能否检查一下 str(yourdata)?这里我有一个 character 类。如果它是因子,请转换为 character - akrun
1
我认为问题是由于数据中有一些POSIXct格式,已转换为character - lentz

9

编辑更新到filter(if_all/if_any)语法(dplyr vs. 1.0.10),以前使用across(现在已弃用)甚至更早之前的filter_allfilter_any(已被取代)。

这里是一个dplyr选项:(使用Akrun的数据)

library(dplyr)

df1 <- structure(list(time = c("1:00", "2:00", "no_data", "3:00"), speed = c("30", "no_data", "no_data", "50"), wheels = c("no_data", "18", "no_data", "18")), .Names = c("time", "speed", "wheels"), class = "data.frame", row.names = c(NA, -4L))

## with if_any
df1 %>% filter(if_any(everything(), ~ grepl("no_data", .)))
#>      time   speed  wheels
#> 1    1:00      30 no_data
#> 2    2:00 no_data      18
#> 3 no_data no_data no_data

## or with if_all
df1 %>% filter(if_all(everything(), ~ !grepl("no_data", .)))
#>   time speed wheels
#> 1 3:00    50     18

## to GET all rows that fulfil condition, use
df1 %>% filter(if_any(everything(), ~ grepl("no_data", .)))
#>      time   speed  wheels
#> 1    1:00      30 no_data
#> 2    2:00 no_data      18
#> 3 no_data no_data no_data

8
您可以使用na.strings='no_data'将数据设置为NA,然后简单地省略NAs(或使用complete.cases),即(使用@akrun的数据集)
d1 <- read.table(text = 'time   speed  wheels
 1    1:00      30 no_data
            2    2:00 no_data      18
            3 no_data no_data no_data
            4    3:00      50      18', na.strings = 'no_data', h=TRUE)

d1[complete.cases(d1),]
#  time speed wheels
#4 3:00    50     18

#OR

na.omit(d1)
#  time speed wheels
#4 3:00    50     18

谢谢@akrun。我无法直接从OP数据中获取它,因为有些元素是“no_data”,其他的是“ no_data”,还有一些是未知的 :) - Sotos

3

akrun的回答快速、正确,尽可能简单易懂 :) 但是,如果你想让自己的生活变得更加复杂,也可以这样做:

dat
     time   speed  wheels
1    1:00      30 no_data
2    2:00 no_data      18
3 no_data no_data no_data
4    3:00      50      18

dat$new <- apply(dat[,1:3], 1, function(x) any(x %in% c("no_data")))
dat <- dat[!(dat$new==TRUE),]
dat$new <- NULL

dat
  time speed wheels
4 3:00    50     18

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