从许多列中相应的选定值中改变列名

问题描述 投票:0回答:2

让我们考虑

markers
及其变异系数 (
cv
) 和三个参考 cv (
rcv
):

初始数据:

  marker    cv  rcv1  rcv2  rcv3
  <chr>  <dbl> <dbl> <dbl> <dbl>
1 AAA        7    10     8     5
2 BBB        4     5     3     1
3 CCC       11    20    15    12
4 DDD        8     7     5     2  

我想改变三个新变量:

  • rcv_value
    :大于
    rcv
    的最接近的
    cv
  • rcv_name
    :该
    rcv_value
  • 的列名称
  • cv_conclusion
    • 确定,如果
      cv
      低于
      rcvs
    • 中的一个或另一个
    • ko 如果
      cv
      高于最高
      rcv

所需输出:

  marker    cv  rcv1  rcv2  rcv3 rcv_value rcv_name cv_conclusion
  <chr>  <dbl> <dbl> <dbl> <dbl>     <dbl> <chr>    <chr>        
1 AAA        7    10     8     5         8 rcv2     ok           
2 BBB        4     5     3     1         5 rcv1     ok           
3 CCC       11    20    15    12        12 rcv3     ok           
4 DDD        8     7     5     2         7 rcv1     ko  

注意:我的真实数据有超过 100 个

markers
和大约 10 个不同的
rcv

我失败的地方是从相应的
rcv_name
中获取
rcv_value
(使用
mutate
case_when
)。

感谢您的帮助。

数据:

dat0 <-
structure(list(marker = c("AAA", "BBB", "CCC", "DDD"), cv = c(7, 
4, 11, 8), rcv1 = c(10, 5, 20, 7), rcv2 = c(8, 3, 15, 5), rcv3 = c(5, 
1, 12, 2)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -4L))
r dataframe dplyr mutate
2个回答
1
投票

你可以试试这个:

library(dplyr)

dat0 %>%
  rowwise() %>% 
  mutate(rcv_value = {
    x <- c_across(rcv1:rcv3)
    x[order(abs(x - cv), -x)][1]
  }) %>%
  ungroup() %>%
  mutate(
    rcv_name = do.call(coalesce, across(rcv1:rcv3, ~ ifelse(.x == rcv_value, cur_column(), NA))),
    cv_conclusion = ifelse(rcv_value >= cv, "ok", "ko")
  )

# # A tibble: 4 × 8
#   marker    cv  rcv1  rcv2  rcv3 rcv_value rcv_name cv_conclusion
#   <chr>  <dbl> <dbl> <dbl> <dbl>     <dbl> <chr>    <chr>        
# 1 AAA        7    10     8     5         8 rcv2     ok           
# 2 BBB        4     5     3     1         5 rcv1     ok           
# 3 CCC       11    20    15    12        12 rcv3     ok           
# 4 DDD        8     7     5     2         7 rcv1     ko

0
投票

在这种情况下,重新整形为长会让事情变得更加简单。首先使用

tidyr::pivot_longer()
,然后
dplyr::mutate(.by = marker)
按组执行这些操作,然后
tidyr::pivot_wider()
将数据恢复到原始形状。

library(dplyr)
library(tidyr)

dat0 |>
    pivot_longer(
        -c(marker, cv),
        names_to = "rcv"
    ) |>
    mutate(
        rcv_value = min(value[value > cv]),
        cv_conclusion = if_else(is.infinite(rcv_value), "ko", "ok"),
        rcv_value = if_else(is.infinite(rcv_value), max(value), rcv_value),
        rcv_name = rcv[rcv_value == value],
        .by = marker
    ) |>
    pivot_wider(
        id_cols = c(marker, cv, rcv_value, rcv_name, cv_conclusion),
        names_from = rcv,
        values_from = value
    )  |>
    select(
        # does not drop columns just changes order to specified one
        marker, cv, rcv1:rcv3, rcv_value:cv_conclusion
    )

# # A tibble: 4 × 8
#   marker    cv  rcv1  rcv2  rcv3 rcv_value rcv_name cv_conclusion
#   <chr>  <dbl> <dbl> <dbl> <dbl>     <dbl> <chr>    <chr>        
# 1 AAA        7    10     8     5         8 rcv2     ok           
# 2 BBB        4     5     3     1         5 rcv1     ok           
# 3 CCC       11    20    15    12        12 rcv3     ok           
# 4 DDD        8     7     5     2         7 rcv1     ko    

如果您可以为

rcv1:rcv3
列中的每个标记建立联系,则您必须指定您想要
rcv_name
说的内容。如果您只想要第一个值,您可以将该行更改为
rcv_name = rcv[rcv_value == value][1]
。或者,您可以创建一个列表列来存储所有值,例如
list(rcv[rcv_value == value])
,或将它们粘贴在一起,例如
rcv_name = paste(rcv[rcv_value == value], collapse = ",")
创建类似
"rcv2,rcv3"
的列。

© www.soinside.com 2019 - 2024. All rights reserved.