एक सशर्त (`if`) कथन के आधार पर डेटा फ़्रेम में एक मान बदलें


122

नीचे दिए गए कोड डेटा फ़्रेम में, मैं उस समय के सभी को बदलना चाहूंगा जो इसके B साथ दिखाई देता है b

junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")

यह प्रदान करता है:

   nm val
1   A   a
2   B   b
3   C   c
4   D   d
5   A   e
6   B   f
7   C   g
8   D   h
9   A   i
10  B   j
11  C   k
12  D   l

मेरा प्रारंभिक प्रयास इस तरह से एक forऔर ifबयानों का उपयोग करना था :

for(i in junk$nm) if(i %in% "B") junk$nm <- "b"

लेकिन जैसा कि मुझे विश्वास है कि आप देख सकते हैं, सभी के मूल्यों के प्रतिस्थापित कर देता है junk$nmके साथ b। मैं देख सकता हूं कि यह क्यों कर रहा है, लेकिन मैं इसे केवल जंक $ एनएम के उन मामलों को बदलने के लिए प्राप्त नहीं कर सकता हूं जहां मूल मूल्य था B

नोट: मैं समस्या को हल करने में कामयाब रहा, gsubलेकिन आरआई सीखने के हित में अभी भी जानना चाहूंगा कि काम करने के लिए मेरा मूल दृष्टिकोण कैसे प्राप्त करें (यदि यह संभव है)


1
आप stringsAsFactors = FALSE को मूल data.frame निर्माण में जोड़ना चाह सकते हैं।
jimmyb

@ जिमीबब क्यों? फैक्टर उपयोगी हैं, और आवश्यक है यदि कोई आर के अधिकांश मॉडलिंग कोड के साथ मॉडलिंग कर रहा है। इससे निपटने का सही तरीका यह है कि डेटा एक कारक है। यदि आप इस रूपांतरण की आवश्यकता नहीं चाहते / चाहती हैं तो आप जैसा कह सकते हैं वैसा कर सकते हैं। यदि आप कारक चाहते हैं, तो हेरफेर करने के आसान तरीके हैं @ केनी प्रदर्शन करना चाहते हैं।
गैविन सिम्पसन

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

जवाबों:


217

वर्णों में एनएम कन्वर्ट करने के लिए आसान और फिर परिवर्तन करें:

junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"

संपादित करें: और अगर वास्तव में आपको कारकों के रूप में एनएम बनाए रखने की आवश्यकता है, तो इसे अंत में जोड़ें:

junk$nm <- as.factor(junk$nm)

4
as.character () कारकों के साथ काम करते समय जीवन को इतना आसान बना देता है। +1
ब्रेंडन बर्टेल्सन

4
क्या होगा यदि आपके पास कई कॉलम हैं?
जियोडेक्स

43

मूल्यों को बदलने के लिए एक और उपयोगी तरीका है

library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))

25

संक्षिप्त उत्तर है:

junk$nm[junk$nm %in% "B"] <- "b"

आर परिचय में सूचकांक वैक्टर पर एक नज़र डालें (यदि आप इसे अभी तक नहीं पढ़ते हैं)।


संपादित करें। जैसा कि टिप्पणियों में देखा गया है कि यह समाधान चरित्र वैक्टर के लिए काम करता है इसलिए आपके डेटा पर विफल रहता है।

कारक के लिए सबसे अच्छा तरीका स्तर बदलना है:

levels(junk$nm)[levels(junk$nm)=="B"] <- "b"

लघु जोड़:% का% में उपयोग केवल तभी मदद करता है जब आपके पास दाईं ओर एक सेट हो, जैसा कि c("B","C")। करना junk$nm[junk$nm == "B"]बेहतर तरीका है।
थिलो

1
ओह, एक और, महत्वपूर्ण इसके अलावा: इसे इस तरह से करने से पहले कारक स्तर bको कारक एनएम में जोड़ने की आवश्यकता होती है । यदि आप पात्रों के साथ काम करना चाहते हैं तो डिलॉप का संस्करण वास्तव में बेहतर है, कारक नहीं। (हमेशा अपने वैरिएबल के प्रकार के बारे में सोचें!)
थिलो

डेटा @ कारक द्वारा बनाए गए डेटा पर काम नहीं करता है क्योंकि डेटा कारक हैं। क्या आप एक कदम भूल गए या आपके पास कारकों को रूपांतरित करने से रोकने के लिए वैश्विक सेटिंग है?
गाविन सिम्पसन

4
बीच महत्वपूर्ण अंतर की @Thilo एक %in%और ==है NAसे निपटने: c(1,2,NA)==1देता है TRUE, FALSE, NAलेकिन c(1,2,NA) %in% 1देता है TRUE, FALSE, FALSE। और हाँ मैं यह देखना भूल गया कि क्या यह काम: /
Marek

20

जैसा कि आपके द्वारा दिखाए गए डेटा कारक हैं, यह चीजों को थोड़ा जटिल करता है। @ diliop का उत्तर nmएक चरित्र चर में परिवर्तित करके समस्या का सामना करता है । मूल कारकों को वापस लाने के लिए एक और कदम की आवश्यकता है।

एक विकल्प जगह में कारक के स्तरों में हेरफेर करना है।

> lev <- with(junk, levels(nm))
> lev[lev == "B"] <- "b"
> junk2 <- within(junk, levels(nm) <- lev)
> junk2
   nm val
1   A   a
2   b   b
3   C   c
4   D   d
5   A   e
6   b   f
7   C   g
8   D   h
9   A   i
10  b   j
11  C   k
12  D   l

यह काफी सरल है और मैं अक्सर भूल जाता हूं कि इसके लिए एक प्रतिस्थापन कार्य है levels()

संपादित करें: जैसा कि @Seth द्वारा टिप्पणियों में उल्लेख किया गया है, यह स्पष्टता के नुकसान के बिना एक-लाइनर में किया जा सकता है:

within(junk, levels(nm)[levels(nm) == "B"] <- "b")

6
अच्छा लगा। मैं प्रतिस्थापन समारोह के बारे में नहीं जानता था levels()। कैसे एक लाइनर के बारे में junk <- within(junk, levels(nm)[levels(nm)=="B"] <- "b")?

लेकिन आप इसे दो बार कहते हैं :)
Marek

2
@ मारेक ने सिर को थप्पड़ मारा सिर्फ यह दिखाने के लिए कि किसी को एसओ पर टिप्पणियों का जवाब नहीं देना चाहिए जब वह अच्छी तरह से सो रहा हो। चलिए फिर से कोशिश करते हैं ...
गेविन सिम्पसन

@ सेठ वास्तव में - अच्छा। निश्चित नहीं कि मैंने कदम अलग क्यों किए? शायद एक्सपोज़र के लिए ...
गेविन सिम्पसन

11

एक कमांड में ऐसा करने का सबसे आसान तरीका कमांड का उपयोग करना है whichऔर ऐसा करने से कारकों को चरित्र में बदलने की आवश्यकता नहीं है:

junk$nm[which(junk$nm=="B")]<-"b"

5

आपने एक कारक चर बनाया है nmताकि आपको या तो ऐसा करने से बचना होगा या कारक विशेषताओं में एक अतिरिक्त स्तर जोड़ना होगा। आपको <-डेटा.फ्रेम () में तर्कों का उपयोग करने से भी बचना चाहिए

विकल्प 1:

junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"

विकल्प 2:

levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk

@ समस्या पर आपके इनपुट के लिए धन्यवाद और चर के प्रकार पर विचार करने की आवश्यकता है। मैंने @ diliop का उत्तर स्वीकार कर लिया क्योंकि यह पहला काम था। मुझे पता है कि वहाँ बहुत सारे मुद्दे हैं <- बनाम = लेकिन (अगर इसका संक्षिप्त उत्तर दिया जा सकता है) = का उपयोग क्यों किया जाना चाहिए data.frame?
DQdlM

आप को जोड़ने के लिए की जरूरत नहीं है bएक स्तर के रूप में, बस स्तर है कि बदलने Bके लिए b
गैविन सिम्पसन

@KennyPeanuts: कॉलम नाम एक समस्या है, देखो a <- data.frame(x<-1:10)। इसका कॉलम नाम xएक गड़बड़ नहीं है x....1.10। Data.frame (x = 1: 10) का उपयोग करने के लिए बेहतर है। तब आपको पता चलता है कि आपका कॉलम नाम क्या है।
IRTFM

@ गैविन: प्रतिस्थापित करने की तुलना में जोड़ना आसान है, और यहां तक ​​कि इसे एक कारक बनाने के लिए आसान नहीं है।
IRTFM

@ डविन आसान मैं असहमत हूं - कुछ सरल के लिए मेरा उत्तर देखें। स्तरों को जोड़ना आपको बाहर निकाल सकता है, मॉडलिंग में कहें, predict()जिसके साथ शिकायत होगी कि नए डेटा में कारक स्तर उन मॉडल से मेल नहीं खाते हैं जो मॉडल में फिट होते थे। शॉर्ट कट पर भरोसा करने की अपेक्षा, डेटा को ठीक से फॉर्मेट करने के लिए लंबे समय में क्लीनर। मैं मानता हूं कि इसे एक कारक नहीं बनाना आसान हो सकता है, लेकिन अगर यह पहले से ही एक है, या कुछ मॉडलिंग अभ्यास के लिए एक होने की जरूरत है ...
गेविन सिम्पसन

1

यदि आप वर्ण चर के साथ काम कर रहे हैं (ध्यान दें कि stringsAsFactorsयह गलत है) तो आप प्रतिस्थापित का उपयोग कर सकते हैं:

junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12], stringsAsFactors = FALSE)
colnames(junk) <- c("nm", "val")

junk$nm <- replace(junk$nm, junk$nm == "B", "b")
junk
#    nm val
# 1   A   a
# 2   b   b
# 3   C   c
# 4   D   d
# ...

0
stata.replace<-function(data,replacevar,replacevalue,ifs) {
  ifs=parse(text=ifs)
  yy=as.numeric(eval(ifs,data,parent.frame()))
  x=sum(yy)
  data=cbind(data,yy)
  data[yy==1,replacevar]=replacevalue
  message=noquote(paste0(x, " replacement are made"))
  print(message)
  return(data[,1:(ncol(data)-1)])
}

इस फ़ंक्शन को नीचे पंक्ति का उपयोग करके कॉल करें।

d=stata.replace(d,"under20",1,"age<20")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.