Стандартизировать столбцы данных в R

У меня есть набор данных под названием spam который содержит 58 столбцов и примерно 3500 строк данных, связанных со спам-сообщениями.

Я планирую запустить некоторую линейную регрессию для этого набора данных в будущем, но я хотел бы сделать некоторую предварительную обработку заранее и стандартизировать столбцы, чтобы иметь нулевое среднее значение и единичную дисперсию.

Мне сказали, что лучший способ сделать это с помощью R, поэтому я хотел бы спросить, как мне добиться нормализации с помощью R? Я уже правильно загрузил данные, и я просто ищу несколько пакетов или методов для выполнения этой задачи.

16 ответов

Решение

Я должен предположить, что вы хотели сказать, что вам нужно среднее значение 0 и стандартное отклонение 1. Если ваши данные находятся в кадре данных, и все столбцы являются числовыми, вы можете просто вызвать scale функция на данных, чтобы делать то, что вы хотите.

dat <- data.frame(x = rnorm(10, 30, .2), y = runif(10, 3, 5))
scaled.dat <- scale(dat)

# check that we get mean of 0 and sd of 1
colMeans(scaled.dat)  # faster version of apply(scaled.dat, 2, mean)
apply(scaled.dat, 2, sd)

Использование встроенных функций классно. Понравился этот кот:

Понимая, что вопрос старый и один ответ принят, я предоставлю другой для справки.

scale ограничен тем, что он масштабирует все переменные. Приведенное ниже решение позволяет масштабировать только определенные имена переменных, сохраняя при этом другие переменные без изменений (и имена переменных могут генерироваться динамически):

library(dplyr)

set.seed(1234)
dat <- data.frame(x = rnorm(10, 30, .2), 
                  y = runif(10, 3, 5),
                  z = runif(10, 10, 20))
dat

dat2 <- dat %>% mutate_each_(funs(scale(.) %>% as.vector), 
                             vars=c("y","z"))
dat2

что дает мне это:

> dat
          x        y        z
1  29.75859 3.633225 14.56091
2  30.05549 3.605387 12.65187
3  30.21689 3.318092 13.04672
4  29.53086 3.079992 15.07307
5  30.08582 3.437599 11.81096
6  30.10121 4.621197 17.59671
7  29.88505 4.051395 12.01248
8  29.89067 4.829316 12.58810
9  29.88711 4.662690 19.92150
10 29.82199 3.091541 18.07352

а также

> dat2 <- dat %>% mutate_each_(funs(scale(.) %>% as.vector), 
>                              vars=c("y","z"))
> dat2
          x          y           z
1  29.75859 -0.3004815 -0.06016029
2  30.05549 -0.3423437 -0.72529604
3  30.21689 -0.7743696 -0.58772361
4  29.53086 -1.1324181  0.11828039
5  30.08582 -0.5946582 -1.01827752
6  30.10121  1.1852038  0.99754666
7  29.88505  0.3283513 -0.94806607
8  29.89067  1.4981677 -0.74751378
9  29.88711  1.2475998  1.80753470
10 29.82199 -1.1150515  1.16367556

РЕДАКТИРОВАТЬ: Адресованный комментарий Джулиана: вывод scale является матрицей Nx1, так что в идеале мы должны добавить as.vector преобразовать тип матрицы обратно в векторный тип. Спасибо, Джулиан!

Это 3 года. Тем не менее, я чувствую, что должен добавить следующее:

Наиболее распространенная нормализация - это z-преобразование, где вы вычитаете среднее значение и делите на стандартное отклонение вашей переменной. Результат будет иметь среднее значение =0 и SD =1.

Для этого вам не нужен пакет.

zVar <- (myVar - mean(myVar)) / sd(myVar)

Вот и все.

Пакет 'Caret' предоставляет методы для предварительной обработки данных (например, центрирование и масштабирование). Вы также можете использовать следующий код:

library(caret)
# Assuming goal class is column 10
preObj <- preProcess(data[, -10], method=c("center", "scale"))
newData <- predict(preObj, data[, -10])

Более подробная информация: http://www.inside-r.org/node/86978

Когда я использовал решение, изложенное Дэйсоном, вместо того, чтобы в результате получить фрейм данных, я получил вектор чисел (масштабированные значения моего df).

Если у кого-то возникли те же проблемы, вы должны добавить as.data.frame() в код, например так:

df.scaled <- as.data.frame(scale(df))

Я надеюсь, что это будет полезно для людей, имеющих такую ​​же проблему!

Вы можете легко нормализовать данные, также используя функцию data.Normalization в clusterSim package. Это обеспечивает другой метод нормализации данных.

    data.Normalization (x,type="n0",normalization="column")

аргументы

Икс
тип вектора, матрицы или набора данных
тип нормализации: n0 - без нормализации

n1 - стандартизация ((х-среднее) / SD)

n2 - позиционная стандартизация ((x-медиана) / безумная)

n3 - единица измерения ((среднее значение по х) / диапазон)

n3a - позиционная унификация ((x-медиана) / диапазон)

n4 - унификация с нулевым минимумом ((x-min) / диапазон)

n5 - нормализация в диапазоне <-1,1> ((среднее значение x) / максимальное значение (среднее значение x)))

n5a - нормализация положения в диапазоне <-1,1> ((х-медиана) / макс (абс (х-медиана)))

n6 - частное преобразование (x / sd)

n6a - позиционное коэффициентное преобразование (x / mad)

n7 - коэффициент преобразования (х / диапазон)

n8 - коэффициент преобразования (х / макс)

n9 - коэффициент преобразования (х / среднее)

n9a - позиционное коэффициентное преобразование (х / медиана)

n10 - коэффициент преобразования (х / сумма)

n11 - коэффициент преобразования (x / sqrt (SSQ))

n12 - нормализация ((x-среднее)/sqrt(сумма ((x-среднее) ^ 2)))

n12a - нормализация положения ((x-медиана)/sqrt(сумма ((x-медиана) ^ 2)))

n13 - нормализация с нулем, являющимся центральной точкой ((x-midrange)/(range/2))

нормализация
"столбец" - нормализация по переменной, "строка" - нормализация по объекту

С dplyr v0.7.4 все переменные можно масштабировать с помощью mutate_all():

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tibble)

set.seed(1234)
dat <- tibble(x = rnorm(10, 30, .2), 
              y = runif(10, 3, 5),
              z = runif(10, 10, 20))

dat %>% mutate_all(scale)
#> # A tibble: 10 x 3
#>         x      y       z
#>     <dbl>  <dbl>   <dbl>
#>  1 -0.827 -0.300 -0.0602
#>  2  0.663 -0.342 -0.725 
#>  3  1.47  -0.774 -0.588 
#>  4 -1.97  -1.13   0.118 
#>  5  0.816 -0.595 -1.02  
#>  6  0.893  1.19   0.998 
#>  7 -0.192  0.328 -0.948 
#>  8 -0.164  1.50  -0.748 
#>  9 -0.182  1.25   1.81  
#> 10 -0.509 -1.12   1.16

Конкретные переменные могут быть исключены с помощью mutate_at():

dat %>% mutate_at(scale, .vars = vars(-x))
#> # A tibble: 10 x 3
#>        x      y       z
#>    <dbl>  <dbl>   <dbl>
#>  1  29.8 -0.300 -0.0602
#>  2  30.1 -0.342 -0.725 
#>  3  30.2 -0.774 -0.588 
#>  4  29.5 -1.13   0.118 
#>  5  30.1 -0.595 -1.02  
#>  6  30.1  1.19   0.998 
#>  7  29.9  0.328 -0.948 
#>  8  29.9  1.50  -0.748 
#>  9  29.9  1.25   1.81  
#> 10  29.8 -1.12   1.16

Создано в 2018-04-24 пакетом представлением (v0.2.0).

Опять же, хотя это старый вопрос, он очень актуален! И я нашел простой способ нормализовать определенные столбцы без необходимости каких-либо пакетов:

normFunc <- function(x){(x-mean(x, na.rm = T))/sd(x, na.rm = T)}

Например

x<-rnorm(10,14,2)
y<-rnorm(10,7,3)
z<-rnorm(10,18,5)
df<-data.frame(x,y,z)

df[2:3] <- apply(df[2:3], 2, normFunc)

Вы увидите, что столбцы y и z нормализованы. Пакеты не нужны:-)

Шкала может использоваться как для полного кадра данных, так и для конкретных столбцов. Для определенных столбцов можно использовать следующий код:

trainingSet[, 3:7] = scale(trainingSet[, 3:7]) # For column 3 to 7
trainingSet[, 8] = scale(trainingSet[, 8]) # For column 8 

Полный кадр данных

trainingSet <- scale(trainingSet)

Пакет collapse обеспечивает самую быструю функцию масштабирования - реализованную на C++ с использованием онлайн-алгоритма Welfords:

dat <- data.frame(x = rnorm(1e6, 30, .2), 
                  y = runif(1e6, 3, 5),
                  z = runif(1e6, 10, 20))

library(collapse)
library(microbenchmark)
microbenchmark(fscale(dat), scale(dat))

Unit: milliseconds
        expr       min       lq      mean    median        uq      max neval cld
 fscale(dat)  27.86456  29.5864  38.96896  30.80421  43.79045 313.5729   100  a 
  scale(dat) 357.07130 391.0914 489.93546 416.33626 625.38561 793.2243   100   b

Более того: fscale S3 является общим для векторов, матриц и кадров данных, а также поддерживает операции сгруппированного и / или взвешенного масштабирования, а также масштабирование до произвольных средних значений и стандартных отклонений.

dplyr Пакет имеет две функции, которые делают это.

> require(dplyr)

Чтобы изменить определенные столбцы таблицы данных, вы можете использовать функцию mutate_at(), Чтобы изменить все столбцы, вы можете использовать mutate_all,

Ниже приведен краткий пример использования этих функций для стандартизации данных.

Мутируйте определенные столбцы:

dt = data.table(a = runif(3500), b = runif(3500), c = runif(3500))
dt = data.table(dt %>% mutate_at(vars("a", "c"), scale)) # can also index columns by number, e.g., vars(c(1,3))

> apply(dt, 2, mean)
            a             b             c 
 1.783137e-16  5.064855e-01 -5.245395e-17 

> apply(dt, 2, sd)
        a         b         c 
1.0000000 0.2906622 1.0000000 

Мутировать все столбцы:

dt = data.table(a = runif(3500), b = runif(3500), c = runif(3500))
dt = data.table(dt %>% mutate_all(scale))

> apply(dt, 2, mean)
            a             b             c 
-1.728266e-16  9.291994e-17  1.683551e-16 

> apply(dt, 2, sd)
a b c 
1 1 1 

Прежде чем мне удалось найти эту ветку, у меня была такая же проблема. У меня были зависимые от пользователя типы столбцов, поэтому я написал for цикл проходит через них и получает необходимые столбцы scale"D. Возможно, есть лучшие способы сделать это, но это решило проблему просто отлично:

 for(i in 1:length(colnames(df))) {
        if(class(df[,i]) == "numeric" || class(df[,i]) == "integer") {
            df[,i] <- as.vector(scale(df[,i])) }
        }

as.vector это необходимая часть, потому что оказалось scale делает rownames x 1 матрица, которая обычно не то, что вы хотите иметь в своем data.frame,

@BBKim дал в значительной степени лучший ответ, но это можно сделать короче. Я удивлен, что его еще никто не придумал.

dat <- data.frame(x = rnorm(10, 30, .2), y = runif(10, 3, 5)) dat <- apply(dat, 2, function(x) (x - mean(x)) / sd(x))

Используйте пакет "Recommenderlab". Загрузите и установите пакет. Этот пакет имеет команду "Нормализовать" во встроенном. Это также позволяет вам выбрать один из многих методов нормализации, а именно "центр" или "Z-счет". Следуйте следующему примеру:

## create a matrix with ratings
m <- matrix(sample(c(NA,0:5),50, replace=TRUE, prob=c(.5,rep(.5/6,6))),nrow=5, ncol=10, dimnames = list(users=paste('u', 1:5, sep=&rdquo;), items=paste('i', 1:10, sep=&rdquo;)))

## do normalization
r <- as(m, "realRatingMatrix")
#here, 'centre' is the default method
r_n1 <- normalize(r) 
#here "Z-score" is the used method used
r_n2 <- normalize(r, method="Z-score")

r
r_n1
r_n2

## show normalized data
image(r, main="Raw Data")
image(r_n1, main="Centered")
image(r_n2, main="Z-Score Normalization")

Приведенный ниже код может быть кратчайшим способом добиться этого.

      dataframe <- apply(dataframe, 2, scale)

Функция нормализации из пакета BBMisc была для меня правильным инструментом, поскольку она может работать со значениями NA.

Вот как им пользоваться:

Учитывая следующий набор данных,

    ASR_API     <- c("CV",  "F",    "IER",  "LS-c", "LS-o")
    Human       <- c(NA,    5.8,    12.7,   NA, NA)
    Google      <- c(23.2,  24.2,   16.6,   12.1,   28.8)
    GoogleCloud <- c(23.3,  26.3,   18.3,   12.3,   27.3)
    IBM     <- c(21.8,  47.6,   24.0,   9.8,    25.3)
    Microsoft   <- c(29.1,  28.1,   23.1,   18.8,   35.9)
    Speechmatics    <- c(19.1,  38.4,   21.4,   7.3,    19.4)
    Wit_ai      <- c(35.6,  54.2,   37.4,   19.2,   41.7)
    dt     <- data.table(ASR_API,Human, Google, GoogleCloud, IBM, Microsoft, Speechmatics, Wit_ai)
> dt
   ASR_API Human Google GoogleCloud  IBM Microsoft Speechmatics Wit_ai
1:      CV    NA   23.2        23.3 21.8      29.1         19.1   35.6
2:       F   5.8   24.2        26.3 47.6      28.1         38.4   54.2
3:     IER  12.7   16.6        18.3 24.0      23.1         21.4   37.4
4:    LS-c    NA   12.1        12.3  9.8      18.8          7.3   19.2
5:    LS-o    NA   28.8        27.3 25.3      35.9         19.4   41.7

нормализованные значения можно получить так:

> dtn <- normalize(dt, method = "standardize", range = c(0, 1), margin = 1L, on.constant = "quiet")
> dtn
   ASR_API      Human     Google GoogleCloud         IBM  Microsoft Speechmatics      Wit_ai
1:      CV         NA  0.3361245   0.2893457 -0.28468670  0.3247336  -0.18127203 -0.16032655
2:       F -0.7071068  0.4875320   0.7715885  1.59862532  0.1700986   1.55068347  1.31594762
3:     IER  0.7071068 -0.6631646  -0.5143923 -0.12409420 -0.6030768   0.02512682 -0.01746131
4:    LS-c         NA -1.3444981  -1.4788780 -1.16064578 -1.2680075  -1.24018782 -1.46198764
5:    LS-o         NA  1.1840062   0.9323361 -0.02919864  1.3762521  -0.15435044  0.32382788

где метод, рассчитанный вручную, просто игнорирует столбцы, содержащие НА:

> dt %>% mutate(normalizedHuman = (Human - mean(Human))/sd(Human)) %>% 
+ mutate(normalizedGoogle = (Google - mean(Google))/sd(Google)) %>% 
+ mutate(normalizedGoogleCloud = (GoogleCloud - mean(GoogleCloud))/sd(GoogleCloud)) %>% 
+ mutate(normalizedIBM = (IBM - mean(IBM))/sd(IBM)) %>% 
+ mutate(normalizedMicrosoft = (Microsoft - mean(Microsoft))/sd(Microsoft)) %>% 
+ mutate(normalizedSpeechmatics = (Speechmatics - mean(Speechmatics))/sd(Speechmatics)) %>% 
+ mutate(normalizedWit_ai = (Wit_ai - mean(Wit_ai))/sd(Wit_ai))
  ASR_API Human Google GoogleCloud  IBM Microsoft Speechmatics Wit_ai normalizedHuman normalizedGoogle
1      CV    NA   23.2        23.3 21.8      29.1         19.1   35.6              NA        0.3361245
2       F   5.8   24.2        26.3 47.6      28.1         38.4   54.2              NA        0.4875320
3     IER  12.7   16.6        18.3 24.0      23.1         21.4   37.4              NA       -0.6631646
4    LS-c    NA   12.1        12.3  9.8      18.8          7.3   19.2              NA       -1.3444981
5    LS-o    NA   28.8        27.3 25.3      35.9         19.4   41.7              NA        1.1840062
  normalizedGoogleCloud normalizedIBM normalizedMicrosoft normalizedSpeechmatics normalizedWit_ai
1             0.2893457   -0.28468670           0.3247336            -0.18127203      -0.16032655
2             0.7715885    1.59862532           0.1700986             1.55068347       1.31594762
3            -0.5143923   -0.12409420          -0.6030768             0.02512682      -0.01746131
4            -1.4788780   -1.16064578          -1.2680075            -1.24018782      -1.46198764
5             0.9323361   -0.02919864           1.3762521            -0.15435044       0.32382788

(normalizedHuman составляет список НА...)

Что касается выбора конкретных столбцов для расчета, можно использовать общий метод, например этот:

data_vars <- df_full %>% dplyr::select(-ASR_API,-otherVarNotToBeUsed)
meta_vars <- df_full %>% dplyr::select(ASR_API,otherVarNotToBeUsed)
data_varsn <- normalize(data_vars, method = "standardize", range = c(0, 1), margin = 1L, on.constant = "quiet")
dtn <- cbind(meta_vars,data_varsn)
Другие вопросы по тегам