问题描述
我有一个嵌套的data.frame-df_nested
,其中一列包含df
:
df <- tibble(ID_Value = 1:8,xyz001 = c("text4",NA,"text2"),xyz002 = c(NA,"text3","text1",NA),xyz003 = c(NA,"text2",NA))
我想根据这些要求找到一种方法来改变这个df:
-
mutate(across(matches("\\d")
- 有4种情况-优先4级。 text4
- 如何应用这些条件而不指定列名,因为列名中可以有任何数字。
- 如果列包含所有NA,则不执行任何操作。
我的尝试:
df_nested <- df_nested %>%
mutate(df = map(data,~.x %>%
mutate(across(matches("\\dd"),function (x) {
conditions (ifelse,case_when or other)
...}
此外,我们应该更好地使用across()
,还是vars()
还是一种很好的方法?
预先谢谢你。
预期产量
df <- tibble(ID_Value = 1:8,NA))
解决方法
您可以将rowwise
与c_across
结合使用:
library(dplyr)
library(tidyr)
df %>%
rowwise() %>%
mutate(col = suppressWarnings(max(c_across(matches('\\d+')),na.rm = TRUE)))
# ID_Value xyz001 xyz002 xyz003 col
# <int> <chr> <chr> <chr> <chr>
#1 1 tier4 NA NA tier4
#2 2 NA NA tier1 tier1
#3 3 NA NA NA NA
#4 4 NA tier3 NA tier3
#5 5 NA tier1 tier2 tier2
#6 6 NA NA NA NA
#7 7 NA NA tier2 tier2
#8 8 tier2 NA NA tier2
对字符值取max
没有意义(并生成警告),但是在这里我们可以使用它直接获取输出。
要只保留每一行的最大值,我们可以调整数据的形状:
df %>%
pivot_longer(cols = -ID_Value) %>%
group_by(ID_Value) %>%
mutate(value = replace(value,-which.max(readr::parse_number(value)),NA)) %>%
pivot_wider()
# ID_Value xyz001 xyz002 xyz003
# <int> <chr> <chr> <chr>
#1 1 tier4 NA NA
#2 2 NA NA tier1
#3 3 NA NA NA
#4 4 NA tier3 NA
#5 5 NA NA tier2
#6 6 NA NA NA
#7 7 NA NA tier2
#8 8 tier2 NA NA
,
- 使用
factor
类型指定所需的顺序。 - 在比赛中进行按行或按列的操作。
考虑此功能
max_only <- function(x,lvls) {
fct <- droplevels(factor(x,lvls))
`[<-`(x,as.integer(fct) != length(levels(fct)),NA_character_)
}
然后您可以指定所需的任何订单
> max_only(c("apple","banana",NA_character_),c("banana","apple"))
[1] "apple" NA NA
> max_only(c("apple",c("apple","banana"))
[1] NA "banana" NA
情况1:列操作
df %>%
mutate(across(matches("\\d"),max_only,c("tier1","tier2","tier3","tier4")))
输出(这看起来更像您的预期输出)
# A tibble: 8 x 4
ID_Value xyz001 xyz002 xyz003
<int> <chr> <chr> <chr>
1 1 tier4 NA NA
2 2 NA NA NA
3 3 NA NA NA
4 4 NA tier3 NA
5 5 NA NA tier2
6 6 NA NA NA
7 7 NA NA tier2
8 8 NA NA NA
情况2:逐行操作
df %>%
mutate(as.data.frame(t(apply(
across(matches("\\d")),1L,"tier4")
))))
输出
# A tibble: 8 x 4
ID_Value xyz001 xyz002 xyz003
<int> <chr> <chr> <chr>
1 1 tier4 NA NA
2 2 NA NA tier1
3 3 NA NA NA
4 4 NA tier3 NA
5 5 NA NA tier2
6 6 NA NA NA
7 7 NA NA tier2
8 8 tier2 NA NA
说明
-
[<-
几乎等同于x[...] <- y; x
。如果...
是逻辑向量(即TRUE / FALSE),则x
中被TRUE索引的值将被y
替换。例如,> x <- c("a","b","c") > `[<-`(x,c(FALSE,TRUE,TRUE),NA_character_) [1] "a" NA NA > x[c(FALSE,TRUE)] <- NA_character_; x [1] "a" NA NA
-
NA_character_
是字符类型的NA值。 -
as.integer(fct) != length(levels(fct))
返回与fct
相同长度的逻辑向量。 TRUE索引fct
的值不是最高级别的位置,FALSE索引相反的位置,NA索引NAs。例如,假设fct
看起来像这样> x <- c("apple",NA) > fct <- droplevels(factor(x,"pear"))) > fct [1] apple banana <NA> Levels: apple banana
然后,您可以看到
> as.integer(fct) != length(levels(fct)) [1] TRUE FALSE NA
-
总之,这仅意味着我们将
NA_character_
分配给不等于最高级别但保持NA不变的值。[<-(x,NA_character_)