【问题标题】:modify certain values using ifelse condition in pipe使用管道中的 ifelse 条件修改某些值
【发布时间】:2020-08-20 09:57:13
【问题描述】:

假设我有如下数据框:

df <- structure(list( 
 name = c("A", "A", "A", "A", "B", "B", "B", "B"),
 val = c(100, 200, 300, 400, 0.15, 0.22, 0.31, 0.48)),
 .typeOf = c("factor", "numeric"),
 row.names = c(NA, -8L),
 class = "data.frame")

我想在条形图上使用线图来可视化数据。但是,您可能会看到数据具有不同的比例,因此我无法正常可视化它们。我需要分别从数据框中引入第二个 Y 轴并重新调整对象“B”的值。为此,我使用以下代码:

df %>%
{
 assign("scaleFactor", ifelse(max(.[.$name == "A",2], na.rm = T) > max(.[.$name == "B",2], na.rm = T),
                              max(.[.$name == "A",2], na.rm = T) / max(.[.$name == "B",2], na.rm = T),
                              max(.[.$name == "B",2], na.rm = T) / max(.[.$name == "A",2], na.rm = T)), 
         envir = baseenv())
 . } %>%
 mutate(val = ifelse(max(.[.$name == "A 1",2], na.rm = T) > max(.[.$name == "B",4], na.rm = T),
                     .[.$name == "B",2] <- .[.$name == "B",2] * scaleFactor,
                     .[.$name == "A",2] <- .[.$name == "B",2] * scaleFactor))

首先我需要计算比例因子。它工作正常。然后我需要按比例因子对对象“B”的多个值。在这里我有一个问题。它返回只有一个重复值的第二列。似乎在这种情况下 ifelse 条件不能用作矢量化函数。

但是,如果我在管道/变异之外使用 ifelse 条件,它会起作用。

ifelse(max(df[df$name == "A",2], na.rm = T) > max(df[df$name == "B",2], na.rm = T),
       df[df$name == "B",2] <- df[df$name == "B",2] * scaleFactor,
       df[df$name == "A",2] <- df[df$name == "A",2] * scaleFactor)

任何想法如何使用管道中的 ifelse 条件修改/乘以某些值?

【问题讨论】:

    标签: r


    【解决方案1】:

    Bas 为您提供了解决方案,但您不必事先对其进行扩展!

    ggplot2 允许您引入从第一个轴线性缩放的辅助轴。一个很好的例子可以找到here

    该节目的明星是这段代码

    scale_y_continuous(
        name = expression("Temperature ("~degree~"C)"), 
        sec.axis = sec_axis(~ . * 400 / 30 , name = "Precipitation (mm)"), 
        limits = c(0, 30))
    

    在这里您可以看到手动添加的比例,例如400/30。根据 Bas,在您的情况下,这将是 833。这是我链接的示例的结果:

    您无疑已经考虑过的警告,plots with two Y-axises are often misleading,应谨慎使用。

    只是为了推荐一个替代方案,facet_wrap 允许您按因子或变量 (Docs) 进行分面,或者您可以使用来自ggpubrggarrange 来制作两个单独的图,然后并排显示.

    【讨论】:

    • 很好的答案,TIL。谢谢
    • 感谢您的回答和提供的链接
    【解决方案2】:

    mutate() 语句中的列分配值(就像您对 .[.$name == "B",2] &lt;- 所做的那样)不是您应该使用 mutate 的方式,而且会让人头疼。

    下面的代码给出了您期望的输出。我用max(max_val) / max_val 替换了ifelse,它立即给出了你想要的scaleFactor

    library(dplyr)
    
    df %>% 
      group_by(name) %>% 
      mutate(max_val = max(val, na.rm = T)) %>% 
      ungroup() %>% 
      mutate(scaleFactor = max(max_val) / max_val,
             val_scaled = val * scaleFactor)
    

    这给了

    # A tibble: 8 x 5
      name     val max_val scaleFactor val_scaled
      <chr>  <dbl>   <dbl>       <dbl>      <dbl>
    1 A     100     400             1        100 
    2 A     200     400             1        200 
    3 A     300     400             1        300 
    4 A     400     400             1        400 
    5 B       0.15    0.48        833.       125 
    6 B       0.22    0.48        833.       183.
    7 B       0.31    0.48        833.       258.
    8 B       0.48    0.48        833.       400 
    

    我将多余的列保留在那里,以便您可以看到发生了什么。您可以通过select()ing 只删除您想要的列。

    【讨论】:

    • 感谢您的回答。你解决了我的问题,但是我的问题仍然没有答案。由于使用 mutate 我不能更改/修改某些值,我应该使用哪个函数/方法?可能是case_when(也不起作用)?
    • 使用 mutate,您可以使用例如ifelse 更改某些值,但新值应该是ifelse 语句的结果,并且不应该这样做内部 ifelse 语句。这根本不是mutate 的工作方式。你可以在变异之外做这些事情,但不能在变异内部做。如果你想把它当作管道来处理,你必须使用类似于我提出的方法。
    猜你喜欢
    • 2015-03-13
    • 2019-12-10
    • 2011-10-31
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    相关资源
    最近更新 更多