R跨越并使用两个动态命名的列来计算结果
R mutate across and using two dynamically named columns to calculate result
Test <- tribble(~Date, ~HCl_Konz, ~HCl_Kenn, ~CO_Konz, ~CO_Kenn,
1, 4, "", 4, "",
2, 5, "", 1, "",
3, 2, "X", 6, "BX",
4, 5, "", 4, "",
5, 6, "F", 4, "",
6, 5, "", 9, "EXr")
Param <- c("HCl", "CO")
真正的 tibble 更大,有几列,如 HCl 和 CO,但它们都遵循相同的方案。对于所有这些列,我想将 HCl_Konz 的值设置为 NA,如果列 HCl_Kenn 至少有一个字符“X”或“F”,与 [=22= 相同](如果 CO_Kenn 包含 X 或 F),以及所有其他 XXX_Konz 列。
我尝试了以下代码,但它因以下错误而退出。
Test %>% rowwise() %>%
mutate(across(paste(Param, "_Konz", sep=""), ~ ifelse(str_detect(paste(str_sub(cur_column(),1,-6), "_Kenn", sep=""), "[XF]"), NA_real_, .x)))
代码没有抛出错误,但值没有被 NA 替换。
蒂亚
- 您缺少
~
来将 ifelse(..)
标记为排序函数。
cur_col()
未找到(对我而言),应该是 .
或 .x
- 您
str_detect
使用 _Kenn
等效列的名称,而不是该列中的值;我们还需要添加 cur_data()[[..]]
。
我倾向于不使用 stringr
作为 straight-forward 这样的替换,更喜欢基础 R:
library(dplyr)
Test %>%
mutate(
across(
paste0(Param, "_Konz"),
~ if_else( grepl("[XF]", cur_data()[[ gsub("_Konz", "_Kenn", cur_column()) ]] ),
.[NA], . )
)
)
# # A tibble: 6 x 5
# Date HCl_Konz HCl_Kenn CO_Konz CO_Kenn
# <dbl> <dbl> <chr> <dbl> <chr>
# 1 1 4 "" 4 ""
# 2 2 5 "" 1 ""
# 3 3 NA "X" NA "BX"
# 4 4 5 "" 4 ""
# 5 5 NA "F" 4 ""
# 6 6 5 "" NA "EXr"
出于多种原因,我建议使用 dplyr::if_else
代替 ifelse
,但它附带了 true=
和 false=
参数的严格(且安全!)要求是完全相同的类型。您至少通过使用 NA_real_
认识到其中的大部分内容;我对 .[NA]
的使用是确保我们根据实际数据获得正确 NA
-变体的另一种方法,如果您的某些 Params
是 [=29=,则允许此方法起作用],有些是 numeric
,例如
另一种方法(稍后可能会有所帮助)是旋转数据并一次只处理两列。
library(tidyr) # pivot_longer
Test %>%
pivot_longer(
matches("_(Konz|Kenn)$"),
names_pattern = "(.*)_(.*)", names_to = c("elem", ".value")
) %>%
mutate(
Konz = if_else(grepl("[XF]", Kenn), Konz[NA], Konz)
)
# # A tibble: 12 x 4
# Date elem Konz Kenn
# <dbl> <chr> <dbl> <chr>
# 1 1 HCl 4 ""
# 2 1 CO 4 ""
# 3 2 HCl 5 ""
# 4 2 CO 1 ""
# 5 3 HCl NA "X"
# 6 3 CO NA "BX"
# 7 4 HCl 5 ""
# 8 4 CO 4 ""
# 9 5 HCl NA "F"
# 10 5 CO 4 ""
# 11 6 HCl 5 ""
# 12 6 CO NA "EXr"
这种旋转格式的优点是可以更简单地调用 mutate
,并且(如果您打算绘制此图)更适合 ggplot2
对长数据的偏好。
Test <- tribble(~Date, ~HCl_Konz, ~HCl_Kenn, ~CO_Konz, ~CO_Kenn,
1, 4, "", 4, "",
2, 5, "", 1, "",
3, 2, "X", 6, "BX",
4, 5, "", 4, "",
5, 6, "F", 4, "",
6, 5, "", 9, "EXr")
Param <- c("HCl", "CO")
真正的 tibble 更大,有几列,如 HCl 和 CO,但它们都遵循相同的方案。对于所有这些列,我想将 HCl_Konz 的值设置为 NA,如果列 HCl_Kenn 至少有一个字符“X”或“F”,与 [=22= 相同](如果 CO_Kenn 包含 X 或 F),以及所有其他 XXX_Konz 列。
我尝试了以下代码,但它因以下错误而退出。
Test %>% rowwise() %>%
mutate(across(paste(Param, "_Konz", sep=""), ~ ifelse(str_detect(paste(str_sub(cur_column(),1,-6), "_Kenn", sep=""), "[XF]"), NA_real_, .x)))
代码没有抛出错误,但值没有被 NA 替换。
蒂亚
- 您缺少
~
来将ifelse(..)
标记为排序函数。 cur_col()
未找到(对我而言),应该是.
或.x
- 您
str_detect
使用_Kenn
等效列的名称,而不是该列中的值;我们还需要添加cur_data()[[..]]
。
我倾向于不使用 stringr
作为 straight-forward 这样的替换,更喜欢基础 R:
library(dplyr)
Test %>%
mutate(
across(
paste0(Param, "_Konz"),
~ if_else( grepl("[XF]", cur_data()[[ gsub("_Konz", "_Kenn", cur_column()) ]] ),
.[NA], . )
)
)
# # A tibble: 6 x 5
# Date HCl_Konz HCl_Kenn CO_Konz CO_Kenn
# <dbl> <dbl> <chr> <dbl> <chr>
# 1 1 4 "" 4 ""
# 2 2 5 "" 1 ""
# 3 3 NA "X" NA "BX"
# 4 4 5 "" 4 ""
# 5 5 NA "F" 4 ""
# 6 6 5 "" NA "EXr"
出于多种原因,我建议使用 dplyr::if_else
代替 ifelse
,但它附带了 true=
和 false=
参数的严格(且安全!)要求是完全相同的类型。您至少通过使用 NA_real_
认识到其中的大部分内容;我对 .[NA]
的使用是确保我们根据实际数据获得正确 NA
-变体的另一种方法,如果您的某些 Params
是 [=29=,则允许此方法起作用],有些是 numeric
,例如
另一种方法(稍后可能会有所帮助)是旋转数据并一次只处理两列。
library(tidyr) # pivot_longer
Test %>%
pivot_longer(
matches("_(Konz|Kenn)$"),
names_pattern = "(.*)_(.*)", names_to = c("elem", ".value")
) %>%
mutate(
Konz = if_else(grepl("[XF]", Kenn), Konz[NA], Konz)
)
# # A tibble: 12 x 4
# Date elem Konz Kenn
# <dbl> <chr> <dbl> <chr>
# 1 1 HCl 4 ""
# 2 1 CO 4 ""
# 3 2 HCl 5 ""
# 4 2 CO 1 ""
# 5 3 HCl NA "X"
# 6 3 CO NA "BX"
# 7 4 HCl 5 ""
# 8 4 CO 4 ""
# 9 5 HCl NA "F"
# 10 5 CO 4 ""
# 11 6 HCl 5 ""
# 12 6 CO NA "EXr"
这种旋转格式的优点是可以更简单地调用 mutate
,并且(如果您打算绘制此图)更适合 ggplot2
对长数据的偏好。