将变换后的变量置于其“父”变量附近

时间:2017-11-06 19:48:21

标签: r tidyverse

当我在数据框中创建转换变量时(例如,现有变量的标准化版本),如果它们以这种方式放在它们的“父”变量旁边通常会很方便(例如,varname1,varname1_z,varname2,varname2_z,等等。)。但是新变量的默认位置是在数据帧的末尾。

有没有办法有效地将新创建的变量与其“父”变量放在一起,以便更好地组织数据?

我目前可以使用select()和名为moveme()的自定义函数更改数据框中的变量位置,但我正在尝试使此变量放置过程更加自动化,以便在创建变量时放置变量。

在下面的代码示例中,您将在数据帧的末尾看到我新创建的所有“_z”变量。有没有办法让我们能够以自动化的方式将它们与未标准化的父母放在一起?

感谢您的支持。

library(tidyverse)

mpg %>% 
  mutate_if(is.numeric, funs(z = scale(.) %>% as.double()))

1 个答案:

答案 0 :(得分:1)

一种方法是:

  1. 首先gather()将您的数据转换为“长”格式,并根据需要进行分组
  2. 进行数据转换(例如创建z分数)以添加新列
  3. gather()再次将新旧数据列放在一列
  4. spread()将数据转换为您喜欢的格式。
  5. 以下是一个例子:

    numeric_cols <- mpg %>% select_if(is.numeric) %>% names
    
    mpg %>%
        rownames_to_column %>%
        mutate(rowname = rowname %>% as.numeric) %>%
        gather(param, quantity, !! numeric_cols) %>%
        group_by(param) %>%
        mutate(z_score = scale(quantity)) %>%
        gather(number_type, value, quantity:z_score)  %>%
        unite(new_col_name, param, number_type) %>%
        spread(new_col_name, value)
    

    这会导致数据框的head()

      rowname manufacturer model trans      drv fl class   cty_quantity cty_z_score
    1 1       audi         a4    auto(l5)   f   p  compact 18            0.2681016 
    2 2       audi         a4    manual(m5) f   p  compact 21            0.9729978 
    3 3       audi         a4    manual(m6) f   p  compact 20            0.7380324 
    4 4       audi         a4    auto(av)   f   p  compact 21            0.9729978 
    5 5       audi         a4    auto(l5)   f   p  compact 16           -0.2018293 
    6 6       audi         a4    manual(m5) f   p  compact 18            0.2681016 
      cyl_quantity cyl_z_score displ_quantity displ_z_score hwy_quantity
    1 4            -1.1721058  1.8            -1.2939999    29          
    2 4            -1.1721058  1.8            -1.2939999    29          
    3 4            -1.1721058  2.0            -1.1391962    31          
    4 4            -1.1721058  2.0            -1.1391962    30          
    5 6             0.0689474  2.8            -0.5199816    26          
    6 6             0.0689474  2.8            -0.5199816    26          
      hwy_z_score year_quantity year_z_score
    1 0.9336964   1999          -0.997861   
    2 0.9336964   1999          -0.997861   
    3 1.2695687   2008           0.997861   
    4 1.1016326   2008           0.997861   
    5 0.4298879   1999          -0.997861   
    6 0.4298879   1999          -0.997861   
    

    我认为这有你想要的形式。几个笔记:

    • group_by是必要的,这样就可以为每个参数创建z分数,而不是计算数据集中所有数字的无意义z分数
    • 列以这种方式排列,因为我们执行了unite(..., param, number_type)而不是unite(..., number_type, param)。后者将所有未转换的列组合在一起,然后是所有z-score列。
    • rownames_to_column行是必需的,因为否则起始数据帧的行不是唯一的,这在尝试找出如何重新构建宽数据时会出现spread()个问题。