आर में डेटा कॉलम मानकीकृत करें


209

मेरे पास एक डेटासेट है spamजिसमें 58 कॉलम और स्पैम संदेशों से संबंधित डेटा की लगभग 3500 पंक्तियाँ हैं।

मैं भविष्य में इस डेटासेट पर कुछ रेखीय प्रतिगमन चलाने की योजना बना रहा हूं, लेकिन मैं पहले से कुछ पूर्व-प्रसंस्करण करना चाहता हूं और स्तंभों को शून्य अर्थ और यूनिट संस्करण के लिए मानकीकृत करना चाहता हूं।

मुझे आर के साथ जाने के लिए सबसे अच्छा तरीका बताया गया है, इसलिए मैं पूछना चाहता हूं कि मैं आर के साथ सामान्यीकरण कैसे प्राप्त कर सकता हूं ? मेरे पास पहले से ही डेटा ठीक से लोड है और मैं इस कार्य को करने के लिए कुछ पैकेज या विधियों की तलाश कर रहा हूं।

जवाबों:


533

मुझे लगता है कि आप कहने का मतलब है कि आप 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)

कार्यों में निर्मित का उपयोग उत्तम दर्जे का है। इस बिल्ली की तरह:

यहां छवि विवरण दर्ज करें


24
हां मेरी गलती का मुझे मतलब था 0 मतलब। और यह काफी उत्तम दर्जे की बिल्ली है
होसर

8
+1 उपयोग करने से यह फैट कैट की तरह धीमा भी हो सकता है :) (कोलीनियां यहाँ)
agstudy

1
@agstudy मेला काफी मुझे अधिक / अधिक ColMeans / ColSums का उपयोग करने की आदत डालनी चाहिए। मुझे लगता है कि मैं इसके बारे में तब तक नहीं सोचता, जब तक कि मैं ऐसी स्थिति में नहीं हूं जहां यह वास्तव में मायने रखता है ...
3

137
इस साइट को और अधिक बिल्लियों की आवश्यकता है +1
लवमेव

35
चेतावनी: स्केल भी डेटा फ्रेम को एक मैट्रिक्स में बदल देता है
जूलियन कार्ल्स

88

यह महसूस करते हुए कि प्रश्न पुराना है और एक उत्तर स्वीकार किया गया है, मैं संदर्भ के लिए एक और उत्तर दूंगा।

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_at(c("y", "z"), ~(scale(.) %>% as.vector))
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_at(c("y", "z"), ~(scale(.) %>% as.vector))
> 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

EDIT 1 (2016) : एडेड जूलियन की टिप्पणी: scaleएनएक्स 1 मैट्रिक्स का आउटपुट है , इसलिए आदर्श रूप से हमें as.vectorमैट्रिक्स प्रकार को वेक्टर प्रकार में परिवर्तित करने के लिए जोड़ना चाहिए । धन्यवाद जूलियन!

EDIT 2 (2019) : ड्यूकियो ए की टिप्पणी का हवाला देते हुए: नवीनतम dplyr (संस्करण 0.8) के लिए आपको dplyr बदलने की आवश्यकता है :: सूची के साथ funcs, जैसेdat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))

EDIT 3 (2020) : @mj_whales का धन्यवाद: पुराना समाधान हटा दिया गया है और अब हमें इसका उपयोग करने की आवश्यकता है mutate_at


यह विधि पूरी तरह से काम करती है, विशेष रूप से जब मेरे पास श्रेणीबद्ध और संख्यात्मक चर का संयोजन होता है। मेरा बस एक सवाल है कि इस ऑपरेटर का "%>%" क्या है?
नोहसिंह

9
@ weber85, यह एक "पाइप" ऑपरेटर (कार्यात्मक प्रोग्रामिंग से) है। लिखने के बजाय f(g(x))यह अच्छा लगेगा अगर कोई लिखता है x %>% g %>% f। दूसरे शब्दों में, dat %>% mutate_each_(funs(scale),vars=c("y","z"))बस है mutate_each_(dat,funs(scale),vars=c("y","z"))। ऑपरेटर बहुत मदद करता है जब एक श्रृंखला बहुत लंबी होती है क्योंकि f(g(h(i(j(x)))))पढ़ना बहुत कठिन हो सकता है।
अंकिम

इस दृष्टिकोण का उपयोग करके जिस पैमाने पर लागू किया जाता है उसे वेक्टर (क्लास न्यूमेरिक) से Nx1 मैट्रिसेस में स्थानांतरित किया जाता है। यह हो सकता है (और मेरे मामले में) ने संकुल में कुछ त्रुटियां पैदा की हैं, जो डेटा के प्रत्येक कॉलम को मानती हैं। फ़्रेम एक वेक्टर है।
जूलियन कार्ल

2
नवीनतम के लिए dplyr(संस्करण 0.8) आप परिवर्तन करने की आवश्यकता है dplyr::funcsके साथ list, जैसेdat %>% mutate_each_(list(~scale(.) %>% as.vector), vars=c("y","z"))
Duccio एक

2
mutate_each_()अब पदावनत हो गया है। आप mutate_at()इसके बजाय उपयोग कर सकते हैं । यह करने का नया तरीका होगा:dat2 <- dat %>% mutate_at(c("y", "z"), scale)
mj_whales

60

यह 3 साल पुराना है। फिर भी, मुझे लगता है कि मुझे निम्नलिखित जोड़ना होगा:

सबसे सामान्य सामान्यीकरण z- परिवर्तन है , जहां आप औसत को घटाते हैं और अपने चर के मानक विचलन द्वारा विभाजित करते हैं। परिणाम का मतलब = 0 और sd = 1 होगा।

उसके लिए, आपको किसी पैकेज की आवश्यकता नहीं है।

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

बस।


पूरी तरह से यह प्रदर्शन करने का एक सरल तरीका है। धन्यवाद
पेड्रो नेवेस

और उसका उपयोग करना बहुत आसान बना देता dplyr: mutate(var = (var - mean(var))/sd(var))
रॉबर्टमाइंस

लेकिन क्या इसका उपयोग दो चर के लिए z- स्कोर प्राप्त करने के लिए किया जा सकता है?
lf_araujo

denormalize लिए myVar <- (zVar * sd(zVar)) + mean(zVar), है ना?
Artur_Indio

4
@Artur_Indio लगभग newVar <- (zVar * sd(myVar)) + mean(myVar):। आपको मूल माध्य / sd का उपयोग करना होगा। जैसा कि आपने इसे लिखा था, आप गुणा करेंगे sd(zVar)=1और जोड़ेंगे mean(zVar)=0, इसलिए कुछ भी नहीं बदलेगा :)
random_forest_fanatic

24

'कैरेट' पैकेज प्रीप्रोसेसिंग डेटा (जैसे सेंटिंग और स्केलिंग) के लिए तरीके प्रदान करता है। आप निम्नलिखित कोड का भी उपयोग कर सकते हैं:

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


17

जब मैंने डैसन द्वारा बताए गए समाधान का उपयोग किया, तो परिणामस्वरूप डेटा फ्रेम प्राप्त करने के बजाय, मुझे संख्याओं का वेक्टर (मेरे डीएफ के स्केल किए गए मान) मिला।

यदि किसी को समान परेशानी हो रही है, तो आपको कोड को as.data.frame () को इस तरह जोड़ना होगा:

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

मुझे आशा है कि यह ppl के लिए एक ही मुद्दा होने के लिए उपयोगी होगा!


अच्छा समाधान! यदि कोई ऐसे कॉलम को छोड़ना चाहता है, जिसे आप स्केल कर सकते हैं, तो आप इसे इस तरह से कर सकते हैं: train_dt[-24] <- scale(train_dt[-24]) जहाँ "24" कॉलम नंबर को बाहर रखा जाना है
NetEmmanuel

13

आप डेटा का उपयोग करके डेटा को आसानी से सामान्य कर सकते हैं। क्लस्टर पैकेज में सामान्यीकरण फ़ंक्शन। यह डेटा को सामान्य बनाने की विभिन्न विधि प्रदान करता है।

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

तर्क

x
वेक्टर, मैट्रिक्स या डेटासेट प्रकार
सामान्यीकरण का प्रकार: n0 - सामान्यीकरण के बिना

n1 - मानकीकरण ((x- माध्य) / sd)

n2 - स्थितिगत मानकीकरण ((एक्स-माध्यियन) / पागल)

n3 - इकाईकरण ((x- माध्य) / श्रेणी)

n3a - स्थितिगत इकाईकरण ((एक्स-माध्यियन) / श्रेणी)

n4 - शून्य न्यूनतम ((x-min) / श्रेणी) के साथ इकाईकरण

n5 - सीमा में सामान्यीकरण <-1,1> (((x- माध्य) / अधिकतम (पेट (x- माध्य))

n5a - श्रेणी में स्थितीय सामान्यीकरण <-1,1> ((x-median) / max (abs (x-median))

n6 - भागफल रूपांतरण (x / sd)

n6a - स्थितीय भागफल परिवर्तन (x / पागल)

n7 - भागफल परिवर्तन (x / रेंज)

n8 - भागफल परिवर्तन (x / अधिकतम)

n9 - भागफल परिवर्तन (x / माध्य)

n9a - स्थितीय भागफल परिवर्तन (x / मंझला)

n10 - भागफल रूपांतरण (x / sum)

n11 - भागफल रूपांतरण (x / sqrt (SSQ))

n12 - सामान्यीकरण ((x- माध्य) / sqrt (योग ((x- माध्य) ^ 2)))

n12a - स्थितिगत सामान्यीकरण ((x-मंझला) / sqrt (योग ((x-median) ^ 2)))

n13 - केंद्रीय बिंदु ((x-midrange) / (रेंज / 2) शून्य होने के साथ सामान्यीकरण)

सामान्यीकरण
"कॉलम" - चर द्वारा सामान्यीकरण, "पंक्ति" - वस्तु द्वारा सामान्यीकरण


यह पैकेज R संस्करण 3.4.3
JdP

11

dplyrV0.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 ) द्वारा बनाया गया ।


9

फिर, भले ही यह एक पुराना सवाल है, यह बहुत प्रासंगिक है! और मुझे किसी भी पैकेज की आवश्यकता के बिना कुछ कॉलम को सामान्य करने का एक सरल तरीका मिल गया है:

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 कॉलम सामान्य हो चुके हैं। कोई पैकेज की जरूरत :-)


8

स्केल का उपयोग पूर्ण डेटा फ्रेम और विशिष्ट कॉलम दोनों के लिए किया जा सकता है। विशिष्ट कॉलम के लिए, निम्नलिखित कोड का उपयोग किया जा सकता है:

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

पूर्ण डेटा फ्रेम

trainingSet <- scale(trainingSet)

3

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 

1

इससे पहले कि मैं इस धागे को ढूंढता, मुझे वही समस्या थी। मेरे पास उपयोगकर्ता आश्रित स्तंभ प्रकार थे, इसलिए मैंने लिखा कि forउनके माध्यम से एक लूप जा रहा है और आवश्यक कॉलम प्राप्त करना है scale। संभवतः इसे करने के बेहतर तरीके हैं, लेकिन इससे समस्या ठीक हो गई:

 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


0

पैकेज का उपयोग करें "प्रमेन्दरलाब"। पैकेज डाउनलोड और इंस्टॉल करें। इस पैकेज में निर्मित में "सामान्यीकृत" एक कमांड है। यह आपको सामान्यीकरण के लिए कई तरीकों में से एक चुनने की अनुमति देता है जैसे कि 'केंद्र' या 'जेड-स्कोर' निम्न उदाहरण का पालन करें:

## 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")

1
यह उत्तर प्रश्न को संबोधित नहीं करता है।
f0nzie

0

सामान्य के बाद से यह लागू नहीं मान के साथ सौदा कर सकते हैं BBMisc पैकेज से समारोह मेरे लिए सही उपकरण था।

यहाँ इसका उपयोग कैसे किया जाता है:

निम्नलिखित डाटासेट को देखते हुए,

    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

जहां हाथ की गणना विधि सिर्फ NA युक्त कोलमों को अनदेखा करती है:

> 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

(सामान्यीकृत हनुमान को NA की सूची में बनाया गया है ...)

गणना के लिए विशिष्ट स्तंभों के चयन के संबंध में, एक सामान्य विधि को इस तरह नियोजित किया जा सकता है:

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)

0

@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))

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.