使用 dplyr [r] 标准化变量

Pet*_*etr 8 r dplyr tidyr tidyverse

我想标准化 R 中的变量。我知道如何做到这一点的多种方法。然而,我真的很喜欢使用下面这种方法:

library(tidyverse)

df <- mtcars

df %>% 
  gather() %>% 
  group_by(key) %>% 
  mutate(value = value - mean(value)) %>% 
  ungroup() %>% 
  pivot_wider(names_from = key, values_from = value)
Run Code Online (Sandbox Code Playgroud)

由于某种原因,这种方法不起作用,因为我无法将数据返回到原始格式。所以想请教一下

Kon*_*rad 8

根据当前文档,您应该使用across基于 - 的语法对所需的列子集执行操作。您可以使用everything选择所有列或使用任何其他可用的限定符group_by仅当您希望对组执行操作时才应使用动词。group_by不是选择变量的正确选择。

\n
mtcars %>%\n    as_tibble() %>%\n    mutate(across(where(is.numeric), ~ . - mean(.)))\n
Run Code Online (Sandbox Code Playgroud)\n

至于实际标准化或您想要应用于列子集的任何其他操作,您可以使用:

\n
\n

.fns 应用于每个选定列的函数。可能的\n值为:

\n
    \n
  • NULL,返回未转换的列。
  • \n
  • 一个函数,例如mean.
  • \n
  • purrr 风格的 lambda,例如~ mean(.x, na.rm = TRUE)
  • \n
  • 函数/lambda 列表,例如list(mean = mean, n_miss = ~ sum(is.na(.x))
  • \n
\n
\n

所以scale你可以这样做:

\n
mtcars %>%\n    as_tibble() %>%\n    mutate(across(where(is.numeric), scale))\n
Run Code Online (Sandbox Code Playgroud)\n

或带有附加参数

\n
mtcars %>%\n    as_tibble() %>%\n    mutate(across(where(is.numeric), scale, center = FALSE))\n
Run Code Online (Sandbox Code Playgroud)\n

旁注

\n

正如您从文档中看到的?scale,该函数返回矩阵。在上面的示例中,您将得到只有一列的矩阵,如果这让您感到困扰,您可以这样做:

\n
mtcars %>%\n    as_tibble() %>%\n    mutate(across(where(is.numeric),  ~ scale(.)[,1]))\n
Run Code Online (Sandbox Code Playgroud)\n

比较

\n
>> mtcars %>%\n...     as_tibble() %>%\n...     mutate(across(where(is.numeric),  ~ scale(.)[,1])) %>% \n...     glimpse()\nRows: 32\nColumns: 11\n$ mpg  <dbl> 0.15088482, 0.15088482, 0.44954345, 0.21725341, -0.23073453, -0.33028740, -0.96078\xe2\x80\xa6\n$ cyl  <dbl> -0.1049878, -0.1049878, -1.2248578, -0.1049878, 1.0148821, -0.1049878, 1.0148821, \xe2\x80\xa6\n$ disp <dbl> -0.57061982, -0.57061982, -0.99018209, 0.22009369, 1.04308123, -0.04616698, 1.0430\xe2\x80\xa6\n$ hp   <dbl> -0.53509284, -0.53509284, -0.78304046, -0.53509284, 0.41294217, \n...\n>> \n>> \n>> mtcars %>%\n...     as_tibble() %>%\n...     mutate(across(where(is.numeric), scale)) %>% \n...     glimpse()\nRows: 32\nColumns: 11\n$ mpg  <dbl[,1]> <matrix[32 x 1]>\n$ cyl  <dbl[,1]> <matrix[32 x 1]>\n$ disp <dbl[,1]> <matrix[32 x 1]>\n$ hp   <dbl[,1]> <matrix[32 x 1]>\n...\n
Run Code Online (Sandbox Code Playgroud)\n


Ric*_*c S 1

目前尚不清楚为什么您首先以长格式制作数据然后返回宽格式,也不清楚为什么您不喜欢scale(df)计算速度更快的格式。

无论如何,如果您确实想使用与您喜欢的代码类似的代码,则需要执行进一步的unnest操作才能将数据返回到原始格式。

df %>% 
  gather() %>% 
  group_by(key) %>% 
  mutate(value = value - mean(value)) %>% 
  ungroup() %>% 
  pivot_wider(names_from = key, values_from = value) %>% 
  unnest(everything())

# A tibble: 32 x 11
#       mpg    cyl    disp    hp    drat       wt   qsec     vs     am   gear   carb
#     <dbl>  <dbl>   <dbl> <dbl>   <dbl>    <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
#  1  0.909 -0.188  -70.7  -36.7  0.303  -0.597   -1.39  -0.438  0.594  0.312  1.19 
#  2  0.909 -0.188  -70.7  -36.7  0.303  -0.342   -0.829 -0.438  0.594  0.312  1.19 
#  3  2.71  -2.19  -123.   -53.7  0.253  -0.897    0.761  0.562  0.594  0.312 -1.81 
#  4  1.31  -0.188   27.3  -36.7 -0.517  -0.00225  1.59   0.562 -0.406 -0.688 -1.81 
#  5 -1.39   1.81   129.    28.3 -0.447   0.223   -0.829 -0.438 -0.406 -0.688 -0.812
#  6 -1.99  -0.188   -5.72 -41.7 -0.837   0.243    2.37   0.562 -0.406 -0.688 -1.81 
#  7 -5.79   1.81   129.    98.3 -0.387   0.353   -2.01  -0.438 -0.406 -0.688  1.19 
#  8  4.31  -2.19   -84.0  -84.7  0.0934 -0.0272   2.15   0.562 -0.406  0.312 -0.812
#  9  2.71  -2.19   -89.9  -51.7  0.323  -0.0673   5.05   0.562 -0.406  0.312 -0.812
# 10 -0.891 -0.188  -63.1  -23.7  0.323   0.223    0.451  0.562 -0.406  0.312  1.19 
# ... with 22 more rows
Run Code Online (Sandbox Code Playgroud)

编辑

为了使用最新的tidyr函数,您应该考虑用以下代码替换gather现已停用的。pivot_longer得到的结果是一样的。

df %>% 
  pivot_longer(everything()) %>% 
  group_by(name) %>% 
  mutate(value = value - mean(value)) %>% 
  ungroup() %>% 
  pivot_wider(names_from = name, values_from = value) %>% 
  unnest(everything())
Run Code Online (Sandbox Code Playgroud)

  • 我知道它是计算密集型的,事实上我写了“为什么你不喜欢计算速度更快的scale(df)”。我正在遵循OP的指示,因为他/她说“我知道如何做到这一点的多种方法。但是,我真的很喜欢使用下面的这种方法” (2认同)