【问题标题】:Make data frame with ratios of every column against every other制作每列与其他列的比率的数据框
【发布时间】:2018-03-09 14:57:10
【问题描述】:

这类似于但不完全相同:calculate ratios for every 2 columns in a data frame

我有一个数据框,我想在其中计算每一列与其他列的比率(一个方向可以,我不需要两个方向。)

df <- bind_cols(x = c(1, 2, 3), y = c(2, 3, 4), z = c(3, 4, 5))

ratios_df <- df %>% 
  mutate(x_y = x/y,
         x_z = x/z,
         y_z = y/z) %>% 
  select(-c(x:z))

如何使用更自动化的方法来生成 ratios_df?

【问题讨论】:

    标签: r loops dataframe


    【解决方案1】:

    您可以使用combn 将列组合在一起,然后将第一个与第二个分开:

    combn(df, 2, function(x) x[[1]] / x[[2]])
              [,1]      [,2]      [,3]
    [1,] 0.5000000 0.3333333 0.6666667
    [2,] 0.6666667 0.5000000 0.7500000
    [3,] 0.7500000 0.6000000 0.8000000
    

    您也可以添加名称:

    nam = combn(names(df),2,paste,collapse="_")
    `colnames<-`(combn(df,2,function(x)x[[1]]/x[[2]]),nam)
               x_y       x_z       y_z
    [1,] 0.5000000 0.3333333 0.6666667
    [2,] 0.6666667 0.5000000 0.7500000
    [3,] 0.7500000 0.6000000 0.8000000
    

    【讨论】:

    • 我不知道您可以像这样 (+1) 将 data.frame 直接传递给combn。这种行为是否记录在案? help(combn) 建议 x 应该是一个向量,这是典型的用法。
    • 我确实通过了名单。从来没有读过文档。使用参数simplify=F,您可以看到传递的对象是如何组合的。这将使您知道如何操作它
    【解决方案2】:
    library(dplyr)
    
    df <- bind_cols(x = c(1, 2, 3), y = c(2, 3, 4), z = c(3, 4, 5))
    
    df_ratios <- as.data.frame(lapply(df, function(x) x/df))
    df_ratios
    # x.x       x.y       x.z      y.x y.y       y.z      z.x      z.y z.z
    # 1   1 0.5000000 0.3333333 2.000000   1 0.6666667 3.000000 1.500000   1
    # 2   1 0.6666667 0.5000000 1.500000   1 0.7500000 2.000000 1.333333   1
    # 3   1 0.7500000 0.6000000 1.333333   1 0.8000000 1.666667 1.250000   1
    
    df_ratios <- df_ratios[, sapply(strsplit(colnames(df_ratios), "\\."), function(x) x[1] > x[2])]
    # y.x      z.x      z.y
    # 1 2.000000 3.000000 1.500000
    # 2 1.500000 2.000000 1.333333
    # 3 1.333333 1.666667 1.250000
    

    【讨论】:

    • 又好又简单!如何清理它以仅具有独特的关系?我不需要倒数(如 x/z 和 z/x),也不需要身份(x/x)。
    【解决方案3】:

    另一种方法是先使用combn创建组合,然后进行计算:

    combos <- combn(names(df), 2, simplify = FALSE)
    
    l2 <- lapply(combos, function(x) df[[ x[1] ]] / df[[ x[2] ]])
    
    ratios_df <- setNames(as.data.frame(l2), sapply(l, paste, collapse = '_'))
    

    给出:

    > ratios_df
            x_y       x_z       y_z
    1 0.5000000 0.3333333 0.6666667
    2 0.6666667 0.5000000 0.7500000
    3 0.7500000 0.6000000 0.8000000
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-23
      • 2022-10-07
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 2020-12-13
      • 2021-05-16
      • 2018-12-01
      相关资源
      最近更新 更多