【问题标题】:Replacing column values based on a corresponding column r根据相应的列 r 替换列值
【发布时间】:2019-07-23 19:51:20
【问题描述】:

我有大约 60 个不同的列,其中 30 个列按名称对应于其余 30 个列。我想根据其他对应的值替换这 30 个列值。

  1. 样本数据:
df.wide<-data.frame(
  title=c("A","B","C","D"),
  IM.A=c(0.5,0.1,4.6,5.6),
  LV.A=c(0.7,0,2.5,5),
  IM.B=c(0.2,0.4,2.6,2.2),
  LV.B=c(1,2,4.5,5),
  IM.C=c(2,1,3,4),
  LV.C=c(3,2,5,1)
)

我有更多列 - IM.D~~ LM.D~~ 用于数据中的每个标题。

  1. 我已将数据重新整形为 long 以提取唯一的列名:
df.long <- gather(df.wide, element,value, IM.A:LV.C)
df.long <- select(df.long, c("element"))
df.long <- unique(df.long)
  1. 我已将 LV 和 IM 分成不同的数据。
lv <- as.data.frame(df.long[grep("LV", df.long$element), ])
im <- as.data.frame(df.long[grep("IM", df.long$element), ])
  1. 我不知道如何从这里开始,但基本上我想将列 LV 值更改为 0,如果其对应的 IM 值小于 2.5 并且我还没有在 Internet 上找到解决方案。李>

最终的数据如下所示:

df.wide<-data.frame(
  title=c("A","B","C","D"),
  IM.A=c(0.5,0.1,4.6,5.6),
  LV.A=c(0,0,2.5,5),
  IM.B=c(0.2,0.4,2.6,2.2),
  LV.B=c(0,0,4.5,0),
  IM.C=c(2,1,3,4),
  LV.C=c(0,0,5,1)
)

【问题讨论】:

    标签: r tidyverse


    【解决方案1】:

    也许把你的数据长格式:

    library(data.table)
    setDT(df.wide)
    
    dt.long = melt(df.wide, meas=patterns(IM = "^IM", LV = "^LV"))
    dt.long[, variable := c("A","B","C")[variable]]
    
        title variable  IM  LV
     1:     A        A 0.5 0.7
     2:     B        A 0.1 0.0
     3:     C        A 4.6 2.5
     4:     D        A 5.6 5.0
     5:     A        B 0.2 1.0
     6:     B        B 0.4 2.0
     7:     C        B 2.6 4.5
     8:     D        B 2.2 5.0
     9:     A        C 2.0 3.0
    10:     B        C 1.0 2.0
    11:     C        C 3.0 5.0
    12:     D        C 4.0 1.0
    

    从这里,很容易进行编辑:

    dt.long[IM < 2.5, LV := 0]
    

    如果你想使用 tidyr:据我所知,gather 在转换为长格式时不支持创建两列。下一代函数,pivot_longer 可能。


    我建议尽可能长时间地继续使用长格式的数据,以避免进一步摆弄变量名,但如果您需要恢复为宽格式,则...

    res = dcast(dt.long, title ~ variable, value.var=c("IM", "LV"), sep=".")
    
       title IM_A IM_B IM_C LV_A LV_B LV_C
    1:     A  0.5  0.2    2  0.0  0.0    0
    2:     B  0.1  0.4    1  0.0  0.0    0
    3:     C  4.6  2.6    3  2.5  4.5    5
    4:     D  5.6  2.2    4  5.0  0.0    1
    

    如果您想要相同的列顺序,则需要进一步的步骤:

    setcolorder(res, names(df.wide))
    
       title IM.A LV.A IM.B LV.B IM.C LV.C
    1:     A  0.5  0.0  0.2  0.0    2    0
    2:     B  0.1  0.0  0.4  0.0    1    0
    3:     C  4.6  2.5  2.6  4.5    3    5
    4:     D  5.6  5.0  2.2  0.0    4    1
    

    【讨论】:

      【解决方案2】:

      您可以使用ifelse(df.wide$IM.A &lt; 2.5, 0, df.wide$LV.A)

      假设您的变量以您在df.wideIM.xLV.x 都相互跟随)中描述的方式对所有列进行间隔,您可以执行类似的操作,其中 3 是第一个 LV 列,而 7 是最后一个 LV 列。

      df.wide[,seq(3,7, by = 2)] <- sapply(seq(3,7, by = 2), function(x)
        ifelse(df.wide[,x-1] < 2.5, 0, df.wide[,x])  
      )
      

      但正如@Frank 指出的那样,您确实应该尽可能长时间地使用长格式,以使此类操作更加简单。

      【讨论】:

      • 或者通过T/F矩阵索引df.wide[grep("LV", names(df.wide))][ df.wide[grep("IM", names(df.wide))] &lt; 2.5 ] &lt;- 0
      【解决方案3】:

      这是一种使用开发tidyrpivot_函数的方法。您可以通过运行devtools::install_github("tidyverse/tidyr") 来获取这些信息。

      这展示了枢轴函数的spec 功能,它允许您灵活地指定重塑格式。它的工作方式是规范的每一行都是原始数据帧的输入列(如果使用pivot_longer)。 .name 列具有输入列名称,.value 列具有您希望各个输入列中的值进入的新列的名称。在这里,我们要将所有以"IM" 开头的列的值放入IM 列中,LV 也是如此。最后,我们指定其他变量如何映射到列(这里只是letter)。

      这让我们可以快速pivot_longer,使用if_else 进行所需的替换,然后将pivot_wider 恢复为原始格式。

      library(tidyverse)
      df.wide <- data.frame(
        title = c("A", "B", "C", "D"),
        IM.A = c(0.5, 0.1, 4.6, 5.6),
        LV.A = c(0.7, 0, 2.5, 5),
        IM.B = c(0.2, 0.4, 2.6, 2.2),
        LV.B = c(1, 2, 4.5, 5),
        IM.C = c(2, 1, 3, 4),
        LV.C = c(3, 2, 5, 1)
      )
      
      spec <- tibble(
        `.name` = df.wide %>% select(-title) %>% colnames(),
        `.value` = str_extract(`.name`, "^.{2}"),
        letter = str_extract(`.name`, ".{1}$")
      )
      
      df.wide %>%
        pivot_longer(spec = spec) %>%
        mutate(LV = if_else(IM < 2.5, 0, LV)) %>%
        pivot_wider(spec = spec)
      #> # A tibble: 4 x 7
      #>   title  IM.A  LV.A  IM.B  LV.B  IM.C  LV.C
      #>   <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
      #> 1 A       0.5   0     0.2   0       2     0
      #> 2 B       0.1   0     0.4   0       1     0
      #> 3 C       4.6   2.5   2.6   4.5     3     5
      #> 4 D       5.6   5     2.2   0       4     1
      

      reprex package (v0.3.0) 于 2019 年 7 月 23 日创建

      【讨论】:

        猜你喜欢
        • 2021-12-25
        • 2021-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-31
        • 2023-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多