在 dplyr 环境 is.na(), na_if(), startsWith(), regex 中设置所有以特定字符串开头的值
set na all values that starts with certain string in dplyr environment is.na(), na_if(), startsWith(), regex
我有几个字符和数值变量的数据框。我想将所有以 0/n(
开头的值设置为 NA
。这些值可能分布在多个列中。
示例:
string <- c("asff", "1\n(", '0asfd', '0\n(asdf)')
num <- c(0,1,2,3)
df <- data.frame(string, num)
##
df
string num
1 asff 0
2 1\n( 1
3 0asfd 2
4 0\n(asdf) 3
期望的输出:
string num
1 asff NA
2 1\n( 1
3 NA 2
4 NA 3
通过以下方式将数值变量快速设置为 NA:
df%>%na_if(., 0)
但是字符串在 na_if()
中似乎并不那么容易工作,因为 na_if()
似乎在正则表达式中不工作,是吗?我试过这样的事情:
na_if(., "^0.")
na_if(., "0.")
na_if(., startsWith("0"))
,但错误...
也许是一个带有正则表达式的条件dplyr::mutate(.=ifelse())
,但是我有这些换行符"\n)"
,它们或没有被正则表达式中的"."
捕获。或者带有 mutate(x = str_replace_all())
.
的东西
我可以逐列进行 (df%>%mutate(x = ifelse(startsWith(x, "0"), NA,x )))
),但这样的硬编码太多了。我不能将它应用于所有带有 mutate(across(colnames(), ~ifelse(startsWith(., "0"), NA, .)))
的列,因为数字列会触发错误。
如果您可以使用 mutate
对一列执行此操作,则应该可以使用 mutate_at()
或 mutate_all()
对多个列执行此操作,此处解释:https://dplyr.tidyverse.org/reference/mutate_all.html
在不知道您的数据是什么样子的情况下,我认为您希望mutate_all()
修改所有包含符合您的条件的数据的列。
在这个使用 iris
数据集的示例中,我们将 5
的所有实例替换为单词 five
:
iris %>%
tibble %>%
mutate_all(function(x) str_replace(x, '5', 'five'))
# A tibble: 150 x 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<chr> <chr> <chr> <chr> <chr>
1 five.1 3.five 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.five 0.2 setosa
5 five 3.6 1.4 0.2 setosa
6 five.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 five 3.4 1.five 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.five 0.1 setosa
或者像你的情况,只有当字符串以5
开头时,我们才能做到这一点,使用^5
正则表达式语言(^
表示字符串的开头,5
表示字符串开头的 5
).
iris %>%
tibble %>%
mutate_all(function(x) str_replace(x, '^5', 'five'))
# A tibble: 150 x 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<chr> <chr> <chr> <chr> <chr>
1 five.1 3.5 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 five 3.6 1.4 0.2 setosa
6 five.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 five 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
Update 要更改 entire 值,如果它的开头有一个 5
,您只需更改str_replace
函数更改为可以更改整个值的函数。在这种情况下,我们使用 ifelse
语句
iris %>%
tibble %>%
mutate_all(function(x) ifelse(str_detect(x, '^5'), 'had_five', x))
# A tibble: 150 x 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<chr> <dbl> <chr> <dbl> <int>
1 had_five 3.5 1.4 0.2 1
2 4.9 3 1.4 0.2 1
3 4.7 3.2 1.3 0.2 1
4 4.6 3.1 1.5 0.2 1
5 had_five 3.6 1.4 0.2 1
6 had_five 3.9 1.7 0.4 1
7 4.6 3.4 1.4 0.3 1
8 had_five 3.4 1.5 0.2 1
9 4.4 2.9 1.4 0.2 1
10 4.9 3.1 1.5 0.1 1
另一个更新 从您的评论来看,您似乎只想将该函数应用于字符列。为此,您可以将 mutate_all(your_fun)
替换为 mutate_if(is.character, your_fun)
- 如本答案开头的帮助文档中所述(同一信息页面描述了 mutate_all
、mutate_if
和 mutate_at
).
以您的示例数据为例,我们可以将任何以 '0'
开头的内容设置为 NA。我对你的例子感到困惑 - 你想在字符串的开头寻找 '0'
或 '0\n('
吗?无论哪种方式,都是这样做的:
# sample data
string <- c("asff", "1\n(", '0asfd', '0\n(asdf)')
num <- c(0,1,2,3)
df <- data.frame(string, num)
# for only a 0 at the start of the string
df %>%
mutate_if(is.character, function(x) ifelse(str_detect(x, '^0'), NA, x))
string num
1 asff 0
2 1\n( 1
3 <NA> 2
4 <NA> 3
# for '0\n(' at the start of the string
df %>%
mutate_if(is.character, function(x) ifelse(str_detect(x, '^0\n\('), NA, x))
string num
1 asff 0
2 1\n( 1
3 0asfd 2
4 <NA> 3
我有几个字符和数值变量的数据框。我想将所有以 0/n(
开头的值设置为 NA
。这些值可能分布在多个列中。
示例:
string <- c("asff", "1\n(", '0asfd', '0\n(asdf)')
num <- c(0,1,2,3)
df <- data.frame(string, num)
##
df
string num
1 asff 0
2 1\n( 1
3 0asfd 2
4 0\n(asdf) 3
期望的输出:
string num
1 asff NA
2 1\n( 1
3 NA 2
4 NA 3
通过以下方式将数值变量快速设置为 NA:
df%>%na_if(., 0)
但是字符串在 na_if()
中似乎并不那么容易工作,因为 na_if()
似乎在正则表达式中不工作,是吗?我试过这样的事情:
na_if(., "^0.")
na_if(., "0.")
na_if(., startsWith("0"))
,但错误...
也许是一个带有正则表达式的条件dplyr::mutate(.=ifelse())
,但是我有这些换行符"\n)"
,它们或没有被正则表达式中的"."
捕获。或者带有 mutate(x = str_replace_all())
.
我可以逐列进行 (df%>%mutate(x = ifelse(startsWith(x, "0"), NA,x )))
),但这样的硬编码太多了。我不能将它应用于所有带有 mutate(across(colnames(), ~ifelse(startsWith(., "0"), NA, .)))
的列,因为数字列会触发错误。
如果您可以使用 mutate
对一列执行此操作,则应该可以使用 mutate_at()
或 mutate_all()
对多个列执行此操作,此处解释:https://dplyr.tidyverse.org/reference/mutate_all.html
在不知道您的数据是什么样子的情况下,我认为您希望mutate_all()
修改所有包含符合您的条件的数据的列。
在这个使用 iris
数据集的示例中,我们将 5
的所有实例替换为单词 five
:
iris %>%
tibble %>%
mutate_all(function(x) str_replace(x, '5', 'five'))
# A tibble: 150 x 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<chr> <chr> <chr> <chr> <chr>
1 five.1 3.five 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.five 0.2 setosa
5 five 3.6 1.4 0.2 setosa
6 five.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 five 3.4 1.five 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.five 0.1 setosa
或者像你的情况,只有当字符串以5
开头时,我们才能做到这一点,使用^5
正则表达式语言(^
表示字符串的开头,5
表示字符串开头的 5
).
iris %>%
tibble %>%
mutate_all(function(x) str_replace(x, '^5', 'five'))
# A tibble: 150 x 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<chr> <chr> <chr> <chr> <chr>
1 five.1 3.5 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 five 3.6 1.4 0.2 setosa
6 five.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 five 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
Update 要更改 entire 值,如果它的开头有一个 5
,您只需更改str_replace
函数更改为可以更改整个值的函数。在这种情况下,我们使用 ifelse
语句
iris %>%
tibble %>%
mutate_all(function(x) ifelse(str_detect(x, '^5'), 'had_five', x))
# A tibble: 150 x 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<chr> <dbl> <chr> <dbl> <int>
1 had_five 3.5 1.4 0.2 1
2 4.9 3 1.4 0.2 1
3 4.7 3.2 1.3 0.2 1
4 4.6 3.1 1.5 0.2 1
5 had_five 3.6 1.4 0.2 1
6 had_five 3.9 1.7 0.4 1
7 4.6 3.4 1.4 0.3 1
8 had_five 3.4 1.5 0.2 1
9 4.4 2.9 1.4 0.2 1
10 4.9 3.1 1.5 0.1 1
另一个更新 从您的评论来看,您似乎只想将该函数应用于字符列。为此,您可以将 mutate_all(your_fun)
替换为 mutate_if(is.character, your_fun)
- 如本答案开头的帮助文档中所述(同一信息页面描述了 mutate_all
、mutate_if
和 mutate_at
).
以您的示例数据为例,我们可以将任何以 '0'
开头的内容设置为 NA。我对你的例子感到困惑 - 你想在字符串的开头寻找 '0'
或 '0\n('
吗?无论哪种方式,都是这样做的:
# sample data
string <- c("asff", "1\n(", '0asfd', '0\n(asdf)')
num <- c(0,1,2,3)
df <- data.frame(string, num)
# for only a 0 at the start of the string
df %>%
mutate_if(is.character, function(x) ifelse(str_detect(x, '^0'), NA, x))
string num
1 asff 0
2 1\n( 1
3 <NA> 2
4 <NA> 3
# for '0\n(' at the start of the string
df %>%
mutate_if(is.character, function(x) ifelse(str_detect(x, '^0\n\('), NA, x))
string num
1 asff 0
2 1\n( 1
3 0asfd 2
4 <NA> 3