चयनित स्तंभों के लिए तालिका में NA मान कैसे बदलें


82

NA मानों को बदलने के बारे में बहुत सारे पद हैं। मुझे पता है कि एक व्यक्ति निम्नलिखित तालिका / फ्रेम में NA को प्रतिस्थापित कर सकता है:

x[is.na(x)]<-0

लेकिन, क्या होगा अगर मैं इसे केवल कुछ स्तंभों तक सीमित करना चाहता हूं? आइए मैं आपको एक उदाहरण दिखाता हूं।

सबसे पहले, एक डाटासेट से शुरू करते हैं।

set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
                b=sample(c(1,2,NA), 10, replace=T), 
                c=sample(c(1:5,NA), 10, replace=T))

जो देता है:

    a  b  c
1   1 NA  2
2   2  2  2
3   2  1  1
4   2 NA  1
5  NA  1  2
6   2 NA  5
7   1  1  4
8   1  1 NA
9   2  1  5
10  2  1  1

ठीक है, इसलिए मैं केवल कॉलम 'ए' और 'बी' के प्रतिस्थापन को प्रतिबंधित करना चाहता हूं। मेरा प्रयास था:

x[is.na(x), 1:2]<-0

तथा:

x[is.na(x[1:2])]<-0

जो काम न करे।

मेरा डेटाटेबल प्रयास, जहाँ y<-data.table(x), स्पष्ट रूप से कभी काम नहीं करने वाला था:

y[is.na(y[,list(a,b)]), ]

मैं is.na तर्क के अंदर कॉलम पास करना चाहता हूं लेकिन यह स्पष्ट रूप से काम नहीं करेगा।

मैं एक data.frame और एक data.table में ऐसा करना चाहूंगा। मेरा अंतिम लक्ष्य 'c' को '' a 'और' b 'के तरीके से 1: 2: 0 से 1: 1 में रखना है, क्योंकि यह एक तार्किक चर नहीं है। मेरे पास कॉलम का एक गुच्छा है, इसलिए मैं इसे एक-एक करके नहीं करना चाहता। और, मैं यह जानना चाहूंगा कि यह कैसे करना है।

क्या तुम्हारे पास कोई सुझाव है?

जवाबों:


115

तुम कर सकते हो:

x[, 1:2][is.na(x[, 1:2])] <- 0

या बेहतर (IMHO), चर नामों का उपयोग करें:

x[c("a", "b")][is.na(x[c("a", "b")])] <- 0

दोनों मामलों में, 1:2या c("a", "b")पूर्व-परिभाषित वेक्टर द्वारा प्रतिस्थापित किया जा सकता है।


वह काम करता है। अगर मैं '1' की खोज करना चाहता हूं तो क्या होगा? मैंने इसे बदलने की कोशिश की, लेकिन मैं इसे काम नहीं कर पाया।
jnam27

5
शायद इस तरह:x[, 1:2][x[, 1:2] == 1] <- 0
flodel

@flodel xएक कार्य करने के दौरान ही एक मैट्रिक्स अपने पहले सदस्य के रूप में मैट्रिक्स को क्यों स्वीकार करता है ? क्या यह सुविधा कहीं दस्तावेज है? इसके अलावा मुझे लगता है कि आप दूसरे उदाहरण में कॉलम नामों वाले वैक्टर से पहले अल्पविराम लगाना भूल गए हैं।
चिसेलेड्स एब्स

@ChiseledAbs, मुझे लगता है कि आप मैट्रिक्स अनुक्रमण का उल्लेख कर रहे हैं (उदाहरण के लिए देखें stackoverflow.com/a/13999583/1201032 ), लेकिन यह असाइनमेंट तक सीमित नहीं है, इसका उपयोग डेटा निकालने के लिए भी किया जा सकता है। लापता अल्पविराम के बारे में: नहीं। Data.frames स्तंभों की सूची है इसलिए यदि आप किसी एकल तर्क का उपयोग करते हैं [, तो यह निर्दिष्ट कॉलम निकाल देगा (देखें stackoverflow.com/a/21137524/1201032 )। मुझे उम्मीद है कि यह आपके प्रश्न का उत्तर देगा लेकिन भविष्य में, कृपया इस तरह के बहुत पुराने उत्तरों पर टिप्पणी करने से बचें; इसके बजाय एक नया प्रश्न पोस्ट करें।
फ्लोडेल

In both cases, 1:2 or c("a", "b") can be replaced by a pre-defined vector.जब मैंने एक पूर्वनिर्धारित वेक्टर का उपयोग किया, तो x[Vpredefined][is.na(x[Vpredefined])] <- 0यह मुझे त्रुटि देता है
रोहित सलूजा

30

संपादित करें 2020-06-15

data.table1.12.4 (अक्टूबर 2019) के बाद से , data.tableयह सुविधा प्रदान करने के लिए दो कार्य करता है: nafillऔर setnafill

nafill स्तंभों पर काम कर रहा है:

cols = c('a', 'b')
y[ , (cols) := lapply(.SD, nafill, fill=0), .SDcols = cols]

setnafill तालिकाओं पर काम करता है (प्रतिस्थापन-संदर्भ / जगह में होता है)

setnafill(y, cols=cols, fill=0)
# print y to show the effect
y[]

यह भी अन्य विकल्पों की तुलना में अधिक कुशल होगा; ?nafillअधिक देखने के लिए, अंतिम-अवलोकन-किया-फॉरवर्ड (LOCF) और NAसमय-श्रृंखला के लिए प्रतिरूपण का अगला-अवलोकन-किया-बैकवर्ड (NOCB) संस्करण ।


यह आपके data.tableसंस्करण के लिए काम करेगा :

for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]

वैकल्पिक रूप से, जैसा कि डेविड अर्नबर्ग नीचे बताते हैं, आप उपयोग कर सकते हैं set(साइड बेनिफिट - आप इसे या तो उपयोग कर सकते हैं ) data.frameया data.table:

for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)

इसके लिए धन्यवाद। बस जानना चाहता था, 3 साल, अगर लूप के बिना उपरोक्त करने के तरीके हैं? मुझे लगता है कि यह data.table टीम द्वारा अधिक संक्षिप्त बना दिया गया होगा? धन्यवाद।
info_seekeR

1
@info_seekeR मुझे एक अधिक संक्षिप्त तरीके का पता नहीं है
eddi

यह फ्लोडेल द्वारा चयनित उत्तर की तुलना में बेहतर समाधान है। फ्लोडेल का दृष्टिकोण असाइनमेंट ऑपरेटर <- का उपयोग करता है और इसलिए इसमें अनावश्यक डेटा कॉपी करना शामिल है।
माइकल

@MichaelChirico अपनी टिप्पणी के पहले भाग में, क्या आपने out <- xx डेटा के साथ गलतफहमी से बचने के लिए कदम जोड़ा था । सवाल से हटकर? अन्यथा यह एक और भी छोटा कमांड है: y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]'x' के 'आउट' वेरिएबल नाम और उपयोग को छोड़ देना।
योआन पैग्यूड

@MichaelChirico सच! मैं पूरी तरह से nafill () के बारे में भूल गया
Yoann Pageaud

22

@ रॉटर्ट मैकडॉनल्ड्स के tidyr::replace_na()उत्तर पर बिल्डिंग , यहाँ कुछ dplyrविकल्प दिए गए हैं जो नियंत्रित करने के लिए हैं कि कॉलम NAबदले गए हैं:

library(tidyverse)

# by column type:
x %>%
  mutate_if(is.numeric, ~replace_na(., 0))

# select columns defined in vars(col1, col2, ...):
x %>%
  mutate_at(vars(a, b, c), ~replace_na(., 0))

# all columns:
x %>%
  mutate_all(~replace_na(., 0))

1
इस फ़ंक्शन के साथ मुझे त्रुटि मिलती है Error in replace_na(., 0) : argument "value" is missing, with no default:। कोई सुझाव क्या बदलना है?
टिम एम। शेंदज़ेलेरोज़

17

यह अब रिप्लेस_ना () के साथ टाइडर में तुच्छ है। फ़ंक्शन डेटा के लिए काम करने के लिए प्रकट होता है। टेबल्स के साथ-साथ डेटा। वर्कफ़्लो:

tidyr::replace_na(x, list(a=0, b=0))

2

यह निश्चित नहीं है कि यह अधिक संक्षिप्त है, लेकिन यह फ़ंक्शन डेटा के चयनित कॉलमों में NA (या कोई भी मूल्य जो आपको पसंद है) को बदलने की अनुमति देगा।

update.mat <- function(dt, cols, criteria) {
  require(data.table)
  x <- as.data.frame(which(criteria==TRUE, arr.ind = TRUE))
  y <- as.matrix(subset(x, x$col %in% which((names(dt) %in% cols), arr.ind = TRUE)))
  y
}

इसे लागू करने के लिए:

y[update.mat(y, c("a", "b"), is.na(y))] <- 0

फ़ंक्शन चयनित कॉलम और पंक्तियों (सेल निर्देशांक) का एक मैट्रिक्स बनाता है जो इनपुट मानदंडों को पूरा करता है (इस मामले में is.na == टीआरए)।


1

हम इसे फ़ंक्शन के data.tableसाथ हल कर सकते हैं tidyr::repalce_naऔरlapply

library(data.table)
library(tidyr)
setDT(df)
df[,c("a","b","c"):=lapply(.SD,function(x) replace_na(x,0)),.SDcols=c("a","b","c")]

इस तरह, हम NAस्ट्रिंग के साथ पेस्ट कॉलम भी हल कर सकते हैं । सबसे पहले, हम replace_na(x,""), फिर हम stringr::str_cकॉलम गठबंधन कर सकते हैं!


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

0

एक विशिष्ट कॉलम के लिए, एक विकल्प है sapply

DF <- data.frame(A = letters[1:5],
             B = letters[6:10],
             C = c(2, 5, NA, 8, NA))

DF_NEW <- sapply(seq(1, nrow(DF)),
                    function(i) ifelse(is.na(DF[i,3]) ==
                                       TRUE,
                                       0,
                                       DF[i,3]))

DF[,3] <- DF_NEW
DF

0

यह {data.table} और {stringr} के साथ काफी उपयोगी है

library(data.table)
library(stringr)

x[, lapply(.SD, function(xx) {str_replace_na(xx, 0)})]

FYI करें


0

Data.table y से शुरू करके, आप बस लिख सकते हैं: इस कमांड को बनाने और चलाने
y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]
से library(data.table)पहले मत भूलना y


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