कारकों से वर्णों में data.frame कॉलम बदलें


352

मेरे पास एक डेटा फ्रेम है। चलो उसे बुलाओ bob:

> head(bob)
                 phenotype                         exclusion
GSM399350 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399351 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399352 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399353 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399354 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399355 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-

मैं इस डेटा फ़्रेम की पंक्तियों को संक्षिप्त करना चाहूंगा (यह एक और प्रश्न होगा)। लेकिन देखो:

> class(bob$phenotype)
[1] "factor"

Bobके स्तंभ कारक हैं। इसलिए, उदाहरण के लिए:

> as.character(head(bob))
[1] "c(3, 3, 3, 6, 6, 6)"       "c(3, 3, 3, 3, 3, 3)"      
[3] "c(29, 29, 29, 30, 30, 30)"

मुझे यह समझ में नहीं आता है, लेकिन मुझे लगता है कि ये स्तंभों के कारकों के स्तरों में संकेत हैं (राजा कैक्टैकेस के दरबार के) bob? मेरी जरूरत नहीं।

अजीब तरह से मैं bobहाथ से कॉलम के माध्यम से जा सकता हूं , और कर सकता हूं

bob$phenotype <- as.character(bob$phenotype)

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

बोनस प्रश्न: मैनुअल दृष्टिकोण क्यों काम करता है?


3
अच्छा होगा यदि आप प्रश्न को प्रतिलिपि प्रस्तुत करने योग्य बनायेंगे, ताकि इसमें की संरचना शामिल हो bob
जंगोरकी

जवाबों:


362

मैट और डिर्क पर बस। यदि आप वैश्विक विकल्प को बदले बिना अपने मौजूदा डेटा फ्रेम को फिर से बनाना चाहते हैं, तो आप इसे एक आवेदन विवरण के साथ फिर से बना सकते हैं:

bob <- data.frame(lapply(bob, as.character), stringsAsFactors=FALSE)

यह सभी चर को "वर्ण" में बदल देगा, यदि आप केवल कारकों को परिवर्तित करना चाहते हैं, तो नीचे मरक का समाधान देखें

जैसा कि @hadley बताते हैं, निम्नलिखित अधिक संक्षिप्त है।

bob[] <- lapply(bob, as.character)

दोनों मामलों में, lapplyएक सूची को आउटपुट करता है; हालांकि, आर के जादुई गुणों के कारण, []दूसरे मामले में उपयोग bobऑब्जेक्ट के डेटा.फ्रेम वर्ग को बनाए रखता है , जिससे as.data.frameतर्क के साथ उपयोग करके डेटा में वापस कनवर्ट करने की आवश्यकता समाप्त हो जाती है stringsAsFactors = FALSE


27
शेन, वह भी संख्यात्मक कॉलम को चरित्र में बदल देगा।
डिर्क एडल्डबुलेटेल

@ डर्क: यह सच है, हालांकि यह स्पष्ट नहीं है कि क्या यहाँ एक समस्या है। जाहिर है, चीजों को सही ढंग से सामने लाना सबसे अच्छा उपाय है। मुझे नहीं लगता है कि डेटा प्रकारों को डेटा फ़्रेम में स्वचालित रूप से परिवर्तित करना आसान है। एक विकल्प ऊपर का उपयोग करना है, लेकिन फिर type.convertसब कुछ कास्टिंग करने के बाद उपयोग करें character, फिर factorsवापस characterफिर से करें।
शेन

यह पंक्ति नामों को छोड़ने के लिए लगता है।
पिकोल्को जुऑ

2
@piccolbo आपने bob[] <- उदाहरण में उपयोग किया या bob <- ?? पहले डेटा रखता है। दूसरी सूची में डेटा को बदल दिया जाता है। पंक्ति के नाम को छोड़ दिया जाता है। मैं उत्तर को अद्यतन करूंगा
डेविड लेबॉयर

6
एक प्रकार जो केवल एक अनाम फ़ंक्शन का उपयोग करके कारक कॉलम को चरित्र में परिवर्तित करता है: iris[] <- lapply(iris, function(x) if (is.factor(x)) as.character(x) else {x})
स्टीफन एफ

313

केवल कारकों को बदलने के लिए:

i <- sapply(bob, is.factor)
bob[i] <- lapply(bob[i], as.character)

संस्करण 0.5.0 मेंmutate_if पैकेज dplyr में नया समारोह पेश किया गया था :

library(dplyr)
bob %>% mutate_if(is.factor, as.character) -> bob

RStudio से पैकेज purrr एक और विकल्प देता है:

library(purrr)
library(dplyr)
bob %>% map_if(is.factor, as.character) %>% as_tibble -> bob

मेरे लिए काम नहीं, दुख की बात है। पता नहीं क्यों। शायद इसलिए कि मेरे पास कॉलनेम हैं?
शरद ऋतु १२

@mohawkjohn जारी नहीं किया जाना चाहिए। आपको त्रुटि हुई या परिणाम जैसा कि आपको उम्मीद नहीं थी?
मारेक

2
नोट: purrrलाइन एक सूची देता है, नहीं data.frame!
RoyalTS

यह भी काम करता है अगर आपके पास पहले से ही iएक वेक्टर है colnames()
क्रिया

39

वैश्विक विकल्प

stringsAsFactors: data.frame और read.table के तर्कों के लिए डिफ़ॉल्ट सेटिंग।

FALSEअपनी स्टार्टअप फ़ाइलों (जैसे ~ / .Rprofile) में आप कुछ सेट करना चाहते हैं । कृपया देखें help(options)


5
इसके साथ समस्या यह है कि जब आप अपने कोड को ऐसे वातावरण में निष्पादित करते हैं, जहां .Rprofile फ़ाइल अनुपलब्ध है, तो आपको बग मिल जाएंगे!
वेफरथिन

4
मैं सेटिंग के बजाय स्क्रिप्ट की शुरुआत में इसे कॉल करना चाहता हूं।
gregmacfarlane

22

यदि आप समझते हैं कि कारकों को कैसे संग्रहीत किया जाता है, तो आप इसे पूरा करने के लिए लागू-आधारित कार्यों का उपयोग करने से बच सकते हैं। इसका मतलब यह नहीं है कि लागू समाधान अच्छी तरह से काम नहीं करते हैं।

कारकों को संख्यात्मक सूचकांक के रूप में संरचित किया जाता है जो 'स्तरों' की सूची से बंधा होता है। यह देखा जा सकता है कि क्या आप एक कारक को संख्यात्मक में बदलते हैं। इसलिए:

> fact <- as.factor(c("a","b","a","d")
> fact
[1] a b a d
Levels: a b d

> as.numeric(fact)
[1] 1 2 1 3

अंतिम पंक्ति में लौटे अंक कारक के स्तरों के अनुरूप हैं।

> levels(fact)
[1] "a" "b" "d"

ध्यान दें कि levels()वर्णों की एक सरणी देता है। आप इस तथ्य का उपयोग आसानी से और कॉम्पैक्ट रूप से कारकों को स्ट्रिंग या न्यूमेरिक्स में बदलने के लिए कर सकते हैं:

> fact_character <- levels(fact)[as.numeric(fact)]
> fact_character
[1] "a" "b" "a" "d"

यह संख्यात्मक मानों के लिए भी काम करता है, बशर्ते आप अपनी अभिव्यक्ति को लपेटें as.numeric()

> num_fact <- factor(c(1,2,3,6,5,4))
> num_fact
[1] 1 2 3 6 5 4
Levels: 1 2 3 4 5 6
> num_num <- as.numeric(levels(num_fact)[as.numeric(num_fact)])
> num_num
[1] 1 2 3 6 5 4

यह उत्तर समस्या को संबोधित नहीं करता है, जो है कि मैं अपने डेटा फ्रेम के सभी कारक कॉलम को चरित्र में कैसे परिवर्तित करूं। as.character(f), पठनीयता और दक्षता दोनों में बेहतर है levels(f)[as.numeric(f)]। यदि आप चतुर होना चाहते हैं, तो आप levels(f)[f]इसके बजाय उपयोग कर सकते हैं । ध्यान दें कि जब किसी कारक को संख्यात्मक मानों के साथ परिवर्तित करते हैं, तो आपको कुछ लाभ मिलते as.numeric(levels(f))[f]हैं, जैसे कि, उदाहरण के लिए as.numeric(as.character(f)), लेकिन इसका कारण यह है कि आपको केवल स्तर को सांख्यिक में बदलना होगा और फिर सब्मिट करना होगा। as.character(f)जैसा है ठीक है।
डे नोवो

20

यदि आप एक नया डेटा फ़्रेम चाहते हैं, bobcजहाँ हर कारक वेक्टर bobfको कैरेक्टर वेक्टर में बदला जाए, तो यह आज़माएँ:

bobc <- rapply(bobf, as.character, classes="factor", how="replace")

यदि आप इसे वापस कनवर्ट करना चाहते हैं, तो आप एक तार्किक वेक्टर बना सकते हैं जिसमें कॉलम कारक हैं, और इसका उपयोग चुनिंदा कारक लागू करने के लिए करें

f <- sapply(bobf, class) == "factor"
bobc[,f] <- lapply(bobc[,f], factor)

2
+1 केवल वही करने के लिए जो आवश्यक था (अर्थात संपूर्ण डेटा को परिवर्तित करना। चरित्र के लिए)। यह समाधान एक डेटा.फ्रेम के लिए मजबूत है जिसमें मिश्रित प्रकार होते हैं।
जोशुआ उलरिच

3
यह उदाहरण 'उदाहरणों' के खंड में 'rapply' के लिए होना चाहिए, जैसे: stat.ethz.ch/R-manual/R-devel/library/base/html/rapply.html । किसी को पता है कि कैसे अनुरोध करें कि ऐसा हो?
एमफेटिस

यदि आप एक डेटा फ्रेम के साथ समाप्त करना चाहते हैं, तो साधारण रूप से डेटा.फ़्रेम कॉल में रैपली लपेटें (स्ट्रिंग्सएफ़एफ़एक्टर का उपयोग करके FALSE तर्क पर सेट करें)
Taylored वेब साइट्स

13

मैं आमतौर पर अपने सभी प्रोजेक्ट्स के अलावा इस फंक्शन को बनाता हूं। जल्द और आसान।

unfactorize <- function(df){
  for(i in which(sapply(df, class) == "factor")) df[[i]] = as.character(df[[i]])
  return(df)
}

8

दूसरा तरीका यह है कि इसे लागू करने के लिए परिवर्तित करें

bob2 <- apply(bob,2,as.character)

और एक बेहतर (पिछले वर्ग 'मैट्रिक्स' का है)

bob2 <- as.data.frame(as.matrix(bob),stringsAsFactors=F)

@ शेन की टिप्पणी के बाद: आदेश data.frame प्राप्त करने के लिए, करas.data.frame(lapply(...
aL3xa

7

अद्यतन: यहाँ कुछ काम नहीं करता है का एक उदाहरण है। मैंने सोचा कि यह होगा, लेकिन मुझे लगता है कि स्ट्रिंग्सएफ़एक्टर्स विकल्प केवल चरित्र स्ट्रिंग्स पर काम करता है - यह कारकों को अकेला छोड़ देता है।

इसे इस्तेमाल करे:

bob2 <- data.frame(bob, stringsAsFactors = FALSE)

सामान्यतया, जब भी आपको ऐसे कारकों के साथ समस्या हो रही है जो वर्ण होने चाहिए, तो stringsAsFactorsआपकी मदद करने के लिए एक सेटिंग है (एक वैश्विक सेटिंग सहित)।


1
यह काम करता है, अगर वह इसे सेट bobकरने के लिए शुरू करता है (लेकिन तथ्य के बाद नहीं)।
शेन

सही। बस स्पष्ट होना चाहता था कि यह समस्या को हल नहीं करता है, प्रति से - लेकिन ध्यान देने के लिए धन्यवाद कि यह इसे रोकता है।
मैट पार्कर

7

या आप कोशिश कर सकते हैं transform:

newbob <- transform(bob, phenotype = as.character(phenotype))

बस उस प्रत्येक कारक को रखना सुनिश्चित करें जिसे आप चरित्र में बदलना चाहते हैं।

या आप ऐसा कुछ कर सकते हैं और एक ही झटके में सभी कीटों को मार सकते हैं:

newbob_char <- as.data.frame(lapply(bob[sapply(bob, is.factor)], as.character), stringsAsFactors = FALSE)
newbob_rest <- bob[!(sapply(bob, is.factor))]
newbob <- cbind(newbob_char, newbob_rest)

यह नहीं अच्छा विचार इस तरह कोड में डेटा को गिरवी रखना, मैं कर सकता sapplyहै, अलग से हिस्सा (वास्तव में, यह ऐसा यह करने के लिए बहुत आसान है) लेकिन आप बात समझ ... मैं कोड की जाँच नहीं की है, क्योंकि मैं घर पर नहीं हूं, इसलिए मुझे उम्मीद है कि यह काम करेगा! =)

यह दृष्टिकोण, हालांकि, एक नकारात्मक पहलू है ... आपको बाद में कॉलम को पुनर्गठित करना होगा, जबकि transformआप जो चाहें कर सकते हैं, लेकिन "पैदल-शैली-कोड-लेखन" की कीमत पर ...

तो वहाँ ... =)


6

आपके डेटा फ्रेम की शुरुआत में stringsAsFactors = FALSEसभी गलतफहमियों को अनदेखा करना शामिल है।


4

यदि आप data.tabledata.frame पर संचालन के लिए पैकेज का उपयोग करेंगे तो समस्या मौजूद नहीं है।

library(data.table)
dt = data.table(col1 = c("a","b","c"), col2 = 1:3)
sapply(dt, class)
#       col1        col2 
#"character"   "integer" 

यदि आपके पास पहले से ही डेटासेट में एक कारक कॉलम है और आप उन्हें चरित्र में बदलना चाहते हैं तो आप निम्न कार्य कर सकते हैं।

library(data.table)
dt = data.table(col1 = factor(c("a","b","c")), col2 = 1:3)
sapply(dt, class)
#     col1      col2 
# "factor" "integer" 
upd.cols = sapply(dt, is.factor)
dt[, names(dt)[upd.cols] := lapply(.SD, as.character), .SDcols = upd.cols]
sapply(dt, class)
#       col1        col2 
#"character"   "integer" 

DT मारेक द्वारा प्रस्तावित सैपली फिक्स को मापता है: In [<-.data.table(*tmp*, sapply(bob, is.factor), : Coerced 'character' RHS to 'double' to match the column's type. Either change the target column to 'character' first (by creating a new 'character' vector length 1234 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'double' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.डीएफ को ठीक करना और डीटी को फिर से बनाना आसान है।
मैट चैंबर्स

2

यह मेरे लिए काम करता है - मैं अंत में एक लाइनर लगा

df <- as.data.frame(lapply(df,function (y) if(class(y)=="factor" ) as.character(y) else y),stringsAsFactors=F)


2

शायद एक नया विकल्प?

library("tidyverse")

bob <- bob %>% group_by_if(is.factor, as.character)

1

आप का उपयोग करना चाहिए convertमें hablarहै जिसके साथ पठनीय वाक्यविन्यास संगत देता tidyverseपाइप:

library(dplyr)
library(hablar)

df <- tibble(a = factor(c(1, 2, 3, 4)),
             b = factor(c(5, 6, 7, 8)))

df %>% convert(chr(a:b))

जो आपको देता है:

  a     b    
  <chr> <chr>
1 1     5    
2 2     6    
3 3     7    
4 4     8   

1

साथ dplyr-package लोड उपयोग

bob=bob%>%mutate_at("phenotype", as.character)

यदि आप केवल phenotypeविशेष रूप से- कॉलम को बदलना चाहते हैं ।


0

यह सभी वर्ण को बदलने और फिर संख्यात्मक को संख्यात्मक में बदलने का काम करता है:

makenumcols<-function(df){
  df<-as.data.frame(df)
  df[] <- lapply(df, as.character)
  cond <- apply(df, 2, function(x) {
    x <- x[!is.na(x)]
    all(suppressWarnings(!is.na(as.numeric(x))))
  })
  numeric_cols <- names(df)[cond]
  df[,numeric_cols] <- sapply(df[,numeric_cols], as.numeric)
  return(df)
}

से अनुकूलित: स्वचालित रूप से एक्सेल शीट के स्तंभ प्रकार प्राप्त करें

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