डेटा फ़्रेम में कई कॉलम के कारक से वर्ग को संख्यात्मक में बदलें


82

कारक से बड़ी संख्या में कॉलम को संख्यात्मक में बदलने का सबसे तेज / सर्वोत्तम तरीका क्या है?

मैंने निम्नलिखित कोड का उपयोग किया है लेकिन ऐसा लगता है कि उसने मेरे डेटा को फिर से ऑर्डर किया है।

> head(stats[,1:2])
  rk                 team
1  1 Washington Capitals*
2  2     San Jose Sharks*
3  3  Chicago Blackhawks*
4  4     Phoenix Coyotes*
5  5   New Jersey Devils*
6  6   Vancouver Canucks*

for(i in c(1,3:ncol(stats))) {
    stats[,i] <- as.numeric(stats[,i])
}

> head(stats[,1:2])
  rk                 team
1  2 Washington Capitals*
2 13     San Jose Sharks*
3 24  Chicago Blackhawks*
4 26     Phoenix Coyotes*
5 27   New Jersey Devils*
6 28   Vancouver Canucks*

सबसे अच्छा तरीका क्या है, हर कॉलम का नामकरण निम्नानुसार है:

df$colname <- as.numeric(ds$colname)

4
कोई सामान्य समाधान नहीं है? यहां प्रस्तावित कुछ समाधान केवल कारकों के साथ काम करते हैं, अन्य काम हमेशा कारकों को छोड़कर, और इतने पर ...
स्कैन

जवाबों:


56

रामनाथ के जवाब के आगे, आप जो व्यवहार अनुभव कर रहे हैं as.numeric(x), xवह आर स्तर पर कारक के आंतरिक, संख्यात्मक प्रतिनिधित्व को वापस करने के कारण है। यदि आप उन संख्याओं को संरक्षित करना चाहते हैं जो कारक के स्तर (उनके आंतरिक प्रतिनिधित्व के बजाय) हैं, तो आपको as.character()रामनाथ के उदाहरण के अनुसार पहले चरित्र में बदलना होगा ।

आपका forलूप एक applyकॉल के रूप में उचित है और कोड के इरादे के रूप में थोड़ा अधिक पठनीय हो सकता है। बस इस लाइन को बदलें:

stats[,i] <- as.numeric(stats[,i])

पढ़ने के लिए

stats[,i] <- as.numeric(as.character(stats[,i]))

यह R अकसर किये गए सवाल में 7.10 है।

HTH


2
किसी भी प्रकार के लूप की आवश्यकता नहीं है। बस सूचकांक का उपयोग करें और अनलिस्ट () करें। संपादित करें: मैंने इसे दर्शाते हुए एक उत्तर जोड़ा।
जोरिस मेय्स

यह दृष्टिकोण केवल इस विशिष्ट मामले में काम करता है। मैंने इसका उपयोग स्तंभों में बदलने के लिए किया factorऔर यह काम नहीं किया। sapplyया mutate_ifअधिक सामान्यतः लागू होने वाले समाधान प्रतीत होते हैं।
लियो

@Leo केयर का विस्तार करने के लिए, क्योंकि मुझे पता है कि यह काम करता है। यह ठीक वैसा ही हल है जैसा कि रामनाथ के नीचे है, क्योंकि वह applyलूप चलाने के लिए उपयोग करता है और ओपी forस्पष्ट रूप से लूप का उपयोग कर रहा था । वास्तव में, सभी अत्यधिक मतदान वाले जवाब as.numeric(as.character())मुहावरे का उपयोग करते हैं ।
गैविन सिम्पसन

हां यह कई कॉलम के वर्ग को बदलने के लिए काम करता है numeric, लेकिन यह रिवर्स (कई कॉलम के वर्ग को बदलने के लिए factor) में काम नहीं करता है । यदि आप उन सूचकांकों का उपयोग करते हैं unlist(), जिनकी आपको आवश्यकता होती है और जब वे अक्षरों के साथ कॉलम पर लागू होते हैं, तो यह प्रत्येक एकल वर्ण को अनलिमिटेड करता है, जो आउटपुट को वापस डालते समय इसे और अधिक काम नहीं करता है stats[,i]। यहाँ उत्तर की जाँच करें: stackoverflow.com/questions/45713473/…
सिंह

@ निश्चित रूप से यह रिवर्स में काम नहीं करता है! पृथ्वी पर आपको क्या आभास हुआ कि यह होगा? यह कभी डिजाइन नहीं किया गया था और ओपी ने कभी भी इसके लिए नहीं कहा। पूछे जाने वाले प्रश्नों के उत्तर देना कठिन। यदि आप यहाँ के स्थान पर एक कारक उपयोग as.factor()में बदलना चाहते as.numeric(as.character())हैं और यह ठीक काम करेगा। बेशक, यदि आपके पास स्तंभों का मिश्रण है, तो आपको iचुनिंदा रूप से चुनने की आवश्यकता होगी , लेकिन यह भी मैं तुच्छ है।
गेविन सिम्पसन

73

कारकों को संख्यात्मक में बदलते समय आपको सावधान रहना होगा। यहां कोड की एक पंक्ति है जो कारक से संख्यात्मक तक कॉलम का एक सेट बदल देगी। मैं यहाँ मान रहा हूँ कि स्तम्भों को संख्यात्मक में बदला जाना क्रमशः १, ३, ४ और ५ है। आप इसे अपने अनुसार बदल सकते हैं

cols = c(1, 3, 4, 5);    
df[,cols] = apply(df[,cols], 2, function(x) as.numeric(as.character(x)));

3
यह सही ढंग से काम नहीं करेगा। उदाहरण: x<-as.factor(1:3); df<-data.frame(a=x,y=runif(3),b=x,c=x,d=x)। मुझे नहीं लगता कि applyइस तरह की समस्याओं के लिए उपयुक्त है।
मारेक

1
इन स्थितियों में पूरी तरह से काम करता है लागू करें। मेरे कोड में त्रुटि 2 के बजाय मार्जिन = 1 का उपयोग कर रही थी, क्योंकि फ़ंक्शन को कॉलम वार करने की आवश्यकता है। मैंने अपने उत्तर को उसी के अनुसार संपादित किया है।
रामनाथ

अब यह काम कर रहा है। लेकिन मुझे लगता है कि यह बिना किया जा सकता है apply। मेरा संपादन जांचें
मारेक

2
... या जोरिस के साथ जवाब unlist। और as.characterअपने समाधान में रूपांतरण कारण की जरूरत नहीं है applyधर्मान्तरित df[,cols]करने के लिए characterइसलिए apply(df[,cols], 2, function(x) as.numeric(x))भी काम करेगा।
मारेक

@ रामनाथ , आप =क्यों इस्तेमाल करते हैं ? क्यों नहीं <-?
किटीगर्ल

40

यह एक पंक्ति में किया जा सकता है, लूप की कोई आवश्यकता नहीं है, यह एक फॉर-लूप या एक आवेदन हो। इसके बजाय अनलिस्ट () का उपयोग करें:

# testdata
Df <- data.frame(
  x = as.factor(sample(1:5,30,r=TRUE)),
  y = as.factor(sample(1:5,30,r=TRUE)),
  z = as.factor(sample(1:5,30,r=TRUE)),
  w = as.factor(sample(1:5,30,r=TRUE))
)
##

Df[,c("y","w")] <- as.numeric(as.character(unlist(Df[,c("y","w")])))

str(Df)

संपादित करें: आपके कोड के लिए, यह बन जाता है:

id <- c(1,3:ncol(stats))) 
stats[,id] <- as.numeric(as.character(unlist(stats[,id])))

जाहिर है, यदि आपके पास एक-स्तंभ डेटा फ़्रेम है और आप इसे वेक्टर में परिवर्तित करने के लिए R के स्वचालित आयाम में कमी नहीं चाहते हैं, तो आपको drop=FALSEतर्क जोड़ना होगा ।


1
छोटे सुधार दोनों की सेटिंग recursiveऔर use.namesपैरामीटर हो सकते हैं । unlistFALSE
मारेक

@ मारेक: सच। मुझे यह खेल बहुत पसंद है :-)
जॉरिस मेय्स

मैं सिर्फ भविष्य में जवाब तलाशने वालों के लिए जोड़ने जा रहा हूं, यह op + gavin की विधि के बराबर नहीं है यदि डेटाफ्रेम केवल एक कॉलम का है। यह उस स्थिति में एक वेक्टर में बदल जाएगा, जबकि ऑप्स अभी भी एक डेटाफ्रेम होगा।
themartinmcfly

1
tidyverse के साथ काम करने वालों के लिए: दिलचस्प बात यह है कि यह तब काम नहीं करता है जब ऑब्जेक्ट भी एक तिगुना हो: कोड विफल हो जाता हैDf <- tibble::as_tibble(Df)
tjebo

1
@ टिबले के अपडेट के साथ टिब्बो और डेटा फ्रेम के बीच मोड़, इस पुराने दृष्टिकोण वास्तव में tidyverse में सबसे अच्छा विकल्प नहीं है। आप संयोजन के साथ tidyselect फ़ंक्शन का बेहतर उपयोग करते हैं mutate_if। या जो भी नया तरीका उपलब्ध है, वह अगले पुनरावृत्तियों में उपलब्ध है dplyr...
जोरिस मेय्स

30

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

library(magrittr)
cols = c(1, 3, 4, 5)
df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))

%<>%ऑपरेटर पाइप और reassigns, जो रखते हुए डेटा सफाई और परिवर्तन सरल लिए बहुत उपयोगी है। अब सूची लागू फ़ंक्शन को पढ़ना बहुत आसान है, केवल उस फ़ंक्शन को निर्दिष्ट करके जिसे आप लागू करना चाहते हैं।


2
साफ समाधान। आप एक ब्रैकेट को भूल गए, लेकिन मैं इसे संपादित नहीं कर सकता क्योंकि यह बहुत छोटा है:df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
epo3

1
मुझे नहीं लगता है कि आपको यहां तक ​​कि लपेटने की आवश्यकता है कि लंगोटी df[,cols] %<>% as.numeric(as.character(.))में वही काम करता है
नैट

जब मैं इस कमांड को Error in [.data.table(Results, , cols) : j (the 2nd argument inside [...]) is a single symbol but column name 'cols' is not found. Perhaps you intended DT[,..cols] or DT[,cols,with=FALSE]. This difference to data.frame is deliberate and explained in FAQ 1.1.
आज़माता

कोड इस तरह है:cols <- c("a","b"); df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
उर्वरा शब्बीर

ब्रैकेट अब जोड़ा गया।
जो

9

यहाँ कुछ dplyrविकल्प दिए गए हैं :

# by column type:
df %>% 
  mutate_if(is.factor, ~as.numeric(as.character(.)))

# by specific columns:
df %>% 
  mutate_at(vars(x, y, z), ~as.numeric(as.character(.))) 

# all columns:
df %>% 
  mutate_all(~as.numeric(as.character(.))) 

6

मुझे लगता है कि ucfagls ने पाया कि आपका लूप काम क्यों नहीं कर रहा है।

यदि आप अभी भी एक लूप का उपयोग नहीं करना चाहते हैं तो इसका समाधान इस प्रकार है lapply:

factorToNumeric <- function(f) as.numeric(levels(f))[as.integer(f)] 
cols <- c(1, 3:ncol(stats))
stats[cols] <- lapply(stats[cols], factorToNumeric)

संपादित करें। मुझे सरल समाधान मिला। ऐसा लगता है कि as.matrixचरित्र में परिवर्तित करें। इसलिए

stats[cols] <- as.numeric(as.matrix(stats[cols]))

आपको जो चाहिए वो करना चाहिए।


5

lapply इसके लिए बहुत डिज़ाइन किया गया है

unfactorize<-c("colA","colB")
df[,unfactorize]<-lapply(unfactorize, function(x) as.numeric(as.character(df[,x])))

हाय @transcom, और स्टैकओवरफ़्लो में आपका स्वागत है। ध्यान दें कि यह प्रश्न एक कारक से संख्यात्मक प्रतिनिधित्व में परिवर्तित करने के बारे में है, न कि किसी अन्य तरीके से। मारेक का समाधान देखें।
हारून ने स्टैक ओवरफ्लो

@ आरोन, समझ गया। मैंने ओपी के शीर्षक की अस्पष्टता के कारण इस उत्तर को पोस्ट किया, इस धारणा के तहत काम करना कि अन्य लोग वर्ग की परवाह किए बिना आसानी से कई स्तंभों को बदलने के लिए एक रास्ता खोज सकते हैं। वैसे भी, मैंने अपने उत्तर को और अधिक उचित तरीके से प्रश्न को संबोधित किया है :)
transcom

2

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

df <- data.frame(x = 1:10,
                 y = rep(1:2, 5),
                 k = rnorm(10, 5,2),
                 z = rep(c(2010, 2012, 2011, 2010, 1999), 2),
                 j = c(rep(c("a", "b", "c"), 3), "d"))

convert.magic <- function(obj, type){
  FUN1 <- switch(type,
                 character = as.character,
                 numeric = as.numeric,
                 factor = as.factor)
  out <- lapply(obj, FUN1)
  as.data.frame(out)
}

str(df)
str(convert.magic(df, "character"))
str(convert.magic(df, "factor"))
df[, c("x", "y")] <- convert.magic(df[, c("x", "y")], "factor")

1

मैं यह बताना चाहता हूं कि यदि आपके पास किसी भी कॉलम में NA है, तो केवल सदस्यता का उपयोग करने से काम नहीं चलेगा। यदि कारक में NA हैं, तो आपको रामनाथ द्वारा प्रदान की गई स्क्रिप्ट का उपयोग करना चाहिए।

उदाहरण के लिए

Df <- data.frame(
  x = c(NA,as.factor(sample(1:5,30,r=T))),
  y = c(NA,as.factor(sample(1:5,30,r=T))),
  z = c(NA,as.factor(sample(1:5,30,r=T))),
  w = c(NA,as.factor(sample(1:5,30,r=T)))
)

Df[,c(1:4)] <- as.numeric(as.character(Df[,c(1:4)]))

निम्नलिखित लौटाता है:

Warning message:
NAs introduced by coercion 

    > head(Df)
       x  y  z  w
    1 NA NA NA NA
    2 NA NA NA NA
    3 NA NA NA NA
    4 NA NA NA NA
    5 NA NA NA NA
    6 NA NA NA NA

परंतु:

Df[,c(1:4)]= apply(Df[,c(1:4)], 2, function(x) as.numeric(as.character(x)))

यह दिखाता है:

> head(Df)
   x  y  z  w
1 NA NA NA NA
2  2  3  4  1
3  1  5  3  4
4  2  3  4  1
5  5  3  5  5
6  4  2  4  4

1

आप unfactor()"varhandle" पैकेज फॉर्म CRAN से फ़ंक्शन का उपयोग कर सकते हैं :

library("varhandle")

my_iris <- data.frame(Sepal.Length = factor(iris$Sepal.Length),
                      sample_id = factor(1:nrow(iris)))

my_iris <- unfactor(my_iris)

1

मुझे यह कोड पसंद है क्योंकि यह बहुत आसान है:

  data[] <- lapply(data, function(x) type.convert(as.character(x), as.is = TRUE)) #change all vars to their best fitting data type

यह बिल्कुल वैसा नहीं है जैसा कि (संख्यात्मक में कनवर्ट) के लिए कहा गया था, लेकिन कई मामलों में और भी अधिक उपयुक्त है।


1

df$colname <- as.numeric(df$colname)

मैंने एक कॉलम प्रकार बदलने के लिए इस तरह की कोशिश की और मुझे लगता है कि यह कई अन्य संस्करणों की तुलना में बेहतर है, अगर आप सभी कॉलम प्रकारों को बदलने नहीं जा रहे हैं

df$colname <- as.character(df$colname)

इसके विपरीत।


0

मुझे apply()कॉल के साथ सभी कॉलम को न्यूमेरिक में बदलने में समस्याएँ आईं :

apply(data, 2, as.numeric)

यह समस्या इसलिए सामने आई क्योंकि कुछ तार उनमें कॉमा थे - जैसे "1024.63" के बजाय "1,024.63" - और आर को संख्याओं को प्रारूपित करने का यह तरीका पसंद नहीं है। इसलिए मैंने उन्हें हटा दिया और फिर भाग गया as.numeric():

data = as.data.frame(apply(data, 2, function(x) {
  y = str_replace_all(x, ",", "") #remove commas
  return(as.numeric(y)) #then convert
}))

ध्यान दें कि इसके लिए स्ट्रिंग पैकेज लोड करने की आवश्यकता है।


0

यही मेरे लिए काम कर रहा है। apply()विवश df को समारोह की कोशिश करता मैट्रिक्स और यह रिटर्न एनए के।

numeric.df <- as.data.frame(sapply(df, 2, as.numeric))


0

@ SDahm के उत्तर के आधार पर, यह मेरे लिए "इष्टतम" समाधान था tibble:

data %<>% lapply(type.convert) %>% as.data.table()

इसके लिए आवश्यक है dplyrऔर magrittr


0

मैं एक समान समस्या पर इनमें से एक गुच्छा की कोशिश की और NAs प्राप्त करता रहा। बेस आर में कुछ वास्तव में चिड़चिड़ा व्यवहार होता है, जो आमतौर पर टिविवर्स पैकेज में तय किया जाता है। मैं उनसे बचता था क्योंकि मैं निर्भरता पैदा नहीं करना चाहता था, लेकिन वे जीवन को इतना आसान बनाते हैं कि अब मैं ज्यादातर समय बेस आर समाधान का पता लगाने की कोशिश भी नहीं करता।

यहाँ Tidyverse समाधान है, जो अत्यंत सरल और सुरुचिपूर्ण है:

library(purrr)

mydf <- data.frame(
  x1 = factor(c(3, 5, 4, 2, 1)),
  x2 = factor(c("A", "C", "B", "D", "E")),
  x3 = c(10, 8, 6, 4, 2))

map_df(mydf, as.numeric)

अधिकांश उत्तर (कम से कम सभी शीर्ष उत्तर) संख्यात्मक मानों के बजाय पूर्णांक स्तरों as.numeric(as.character())के सभी-सामान्य रूपांतरण से बचने के लिए रूपांतरण करना सुनिश्चित करते हैं । यदि आप वह विकल्प दिखाते हैं तो मैं इस उत्तर को खुशी से दूंगा।
ग्रेगर थॉमस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.