代码之家  ›  专栏  ›  技术社区  ›  papgeo

计算具有多个变量的加权和

r
  •  2
  • papgeo  · 技术社区  · 11 月前

    我有一个很大的数据集,有很多 x y 列,但显示了下面有5个的示例

    library(dplyr)
    set.seed(505)
    df <- data.frame(
    x1 = sample(-2 : 4,size = 10, replace = TRUE),
    x2 = sample(-2 : 4,size = 10, replace = TRUE),
    x3 = sample(-2 : 4,size = 10, replace = TRUE),  
    x4 = sample(-2 : 4,size = 10, replace = TRUE), 
    x5 = sample(-2 : 4,size = 10, replace = TRUE),   
    y1 = sample(-2 : 4,size = 10, replace = TRUE), 
    y2 = sample(-2 : 4,size = 10, replace = TRUE),
    y3 = sample(-2 : 4,size = 10, replace = TRUE),  
    y4 = sample(-2 : 4,size = 10, replace = TRUE),  
    y5 = sample(-2 : 4,size = 10, replace = TRUE))
    

    我的任务可以用下面的代码实现

    df |> mutate(
      sum1 = x1 * as.numeric(x1 > -1 & y1 > -1) +
             x2 * as.numeric(x2 > -1 & y2 > -1) +
             x3 * as.numeric(x3 > -1 & y3 > -1) +
             x4 * as.numeric(x4 > -1 & y4 > -1) +
             x5 * as.numeric(x5 > -1 & y5 > -1)
    

    因为我有25个 x y 变量,我的问题是:有更好的方法来实现同样的目标吗?

    4 回复  |  直到 11 月前
        1
  •  3
  •   s_baldur    11 月前
    xs <- paste0("x", 1:5)
    ys <- paste0("y", 1:5)
    
    rowSums(df[xs] * (df[xs] > -1 & df[ys] > -1))
    
    # Alternatively
    foo <- \(x, y) replace(x, pmin(x, y) <= -1, 0)
    rowSums(mapply(foo, df[xs], df[ys]))
    
    
    # [1] 2 3 1 4 6 3 0 0 1 2
    
        2
  •  3
  •   Rui Barradas    11 月前

    这是一个基本的R解决方案。
    获取名称以开头的列 "x" 以a开头的 "y" 具有 mapply 计算每对的新值 “x” y 和管道到 rowSums 以获得想要的结果。将所有内容放在一起,并为新列指定名称 "sum1" .

    set.seed(2024)
    df <- data.frame(
      x1 = sample(-2 : 4,size = 10, replace = TRUE),
      x2 = sample(-2 : 4,size = 10, replace = TRUE),
      x3 = sample(-2 : 4,size = 10, replace = TRUE),  
      x4 = sample(-2 : 4,size = 10, replace = TRUE), 
      x5 = sample(-2 : 4,size = 10, replace = TRUE),   
      y1 = sample(-2 : 4,size = 10, replace = TRUE), 
      y2 = sample(-2 : 4,size = 10, replace = TRUE),
      y3 = sample(-2 : 4,size = 10, replace = TRUE),  
      y4 = sample(-2 : 4,size = 10, replace = TRUE),  
      y5 = sample(-2 : 4,size = 10, replace = TRUE))
    
    xnames <- grep("x", names(df), value = TRUE)
    ynames <- grep("y", names(df), value = TRUE)
    
    df <- cbind(df,
          mapply(\(ix, iy, DF) {
            x <- DF[[ix]]
            y <- DF[[iy]]
            x*as.integer(x > -1 & y > -1)
          }, xnames, ynames, MoreArgs = list(DF = df)) |>
            rowSums()
    )
    names(df)[ncol(df)] <- "sum1"
    df
    #>    x1 x2 x3 x4 x5 y1 y2 y3 y4 y5 sum1
    #> 1  -1  4 -1  1  1 -2 -2 -2  3  3    2
    #> 2   2  2 -1  1 -1 -1  3  0 -2  1    2
    #> 3   2  0  2  1  1 -2  1  1 -2  3    3
    #> 4   1  2 -2  0  1 -2 -2  2  2 -2    0
    #> 5   4  3  0 -1  4 -2  4  3  0 -2    3
    #> 6  -2  1  0  1  1  3  2  0  2  1    3
    #> 7   2  3 -2  1 -2 -1  0 -2  1  3    4
    #> 8  -2 -1  3  4  2 -2  2 -2  0  0    6
    #> 9  -1 -1 -2  4  1  0 -1  0  1 -1    4
    #> 10 -1  1  1 -2  0 -2 -1  0  2  0    1
    

    创建于2024-02-01 reprex v2.0.2

        3
  •  1
  •   ThomasIsCoding    11 月前

    你可以试试下面的代码

    > lst <- split.default(df, sub("\\d+", "", names(df)))
    
    > rowSums(lst$x * (do.call(pmin, lst) > -1))
     [1] 2 3 1 4 6 3 0 0 1 2
    
        4
  •  0
  •   uguros    11 月前

    对有一些方法可以更好地处理这项任务。 让我提供我的解决方案如下

    library(dplyr)
    library(purrr)
    
    # Assuming you have 25 x and y columns
    x_cols <- paste0("x", 1:25)
    y_cols <- paste0("y", 1:25)
    
    df <- df %>%
      mutate(sum1 = reduce(
        map2_dbl(x_cols, y_cols, ~ .x * as.numeric(get(.x) > -1 & get(.y) > -1)),
        `+`
      ))