सशर्त मूल्यों के साथ dplyr उत्परिवर्तन


87

चार कॉलम वाले एक बड़े डेटाफ़्रेम ("मायफ़ाइल") में मुझे पहले चार कॉलमों के आधार पर सशर्त रूप से मूल्यों के साथ पांचवां कॉलम जोड़ना होगा।

साथ जवाब पसंद करते हैं dplyrऔर mutateमुख्य रूप से बड़े डेटा सेट में अपनी गति की वजह से।

मेरा डेटाफ़्रेम इस तरह दिखता है:

  V1 V2 V3 V4
1  1  2  3  5
2  2  4  4  1
3  1  4  1  1
4  4  5  1  3
5  5  5  5  4
...

पांचवें कॉलम (V5) के मान कुछ सशर्त नियमों पर आधारित हैं:

if (V1==1 & V2!=4) {
  V5 <- 1
} else if (V2==4 & V3!=1) {
  V5 <- 2
} else {
  V5 <- 0
}

अब मैं mutateसभी पंक्तियों पर इन नियमों का उपयोग करने के लिए फ़ंक्शन का उपयोग करना चाहता हूं (धीमी छोरों से बचने के लिए)। कुछ इस तरह (और हाँ, मुझे पता है कि यह इस तरह से काम नहीं करता है!):

myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
    else if (V2==4 & V3!=1){V5 = 2}
    else {V5 = 0})

यह परिणाम होना चाहिए:

  V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

इसमें कैसे करें dplyr?


यह बताने के लिए उपयोगी है कि क्या V1..4 सभी पूर्णांक (कारक नहीं, तार्किक, स्ट्रिंग या फ्लोट) हैं? और क्या आप सही ढंग से निपटने के बारे में परवाह करते हैं NA, ( NaN, +Inf, -Inf)?
1919

अगर गति को तरजीह देना एक मुद्दा लगता है dplyr, तो मैं बेहतर उपयोग करूंगा data.table
वैलेंटाइन

जवाबों:


105

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

myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))

दे रही है:

  V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

या यह:

myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))

दे रही है:

  V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

ध्यान दें

सुझाव है कि आप अपने डेटा फ्रेम के लिए एक बेहतर नाम प्राप्त करें। myfile बनाता है ऐसा लगता है जैसे यह एक फ़ाइल नाम रखता है।

ऊपर इस इनपुट का इस्तेमाल किया:

myfile <- 
structure(list(V1 = c(1L, 2L, 1L, 4L, 5L), V2 = c(2L, 4L, 4L, 
5L, 5L), V3 = c(3L, 4L, 1L, 1L, 5L), V4 = c(5L, 1L, 1L, 3L, 4L
)), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5"))

अद्यतन 1 क्योंकि मूल रूप से पोस्ट की गई dplyr बदल गई %.%है %>%इसलिए उसके अनुसार संशोधित उत्तर हैं।

अद्यतन 2 dplyr अब case_whenजो एक और समाधान प्रदान करता है:

myfile %>% 
       mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, 
                             V2 == 4 & V3 != 1 ~ 2,
                             TRUE ~ 0))

मैंने आपका दूसरा उपाय आजमाया। मुझे यह त्रुटि मिली: mutate_impl में त्रुटि (.data, name_dots (...), पर्यावरण ()): REAL () केवल 'न्यूमेरिक' पर लागू हो सकती है, 'तार्किक' नहीं क्या आप जानते हैं कि क्या गलत हो रहा है?
rdatasculptor

5
मैंने एक ऐसा तरीका खोजा जिससे आप ifelseबयानों को घोंसला नहीं बना सकते :myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
एलेक्स

31

के साथ dplyr 0.7.2, आप बहुत उपयोगी case_whenफ़ंक्शन का उपयोग कर सकते हैं :

x=read.table(
 text="V1 V2 V3 V4
 1  1  2  3  5
 2  2  4  4  1
 3  1  4  1  1
 4  4  5  1  3
 5  5  5  5  4")
x$V5 = case_when(x$V1==1 & x$V2!=4 ~ 1,
                 x$V2==4 & x$V3!=1 ~ 2,
                 TRUE ~ 0)

के साथ व्यक्त किया dplyr::mutate, यह देता है:

x = x %>% mutate(
     V5 = case_when(
         V1==1 & V2!=4 ~ 1,
         V2==4 & V3!=1 ~ 2,
         TRUE ~ 0
     )
)

कृपया ध्यान दें कि NAविशेष रूप से इलाज नहीं किया जाता है, क्योंकि यह भ्रामक हो सकता है। फ़ंक्शन NAकेवल तभी लौटेगा जब किसी भी स्थिति का मिलान नहीं किया जाएगा। यदि आप के साथ एक लाइन डालते हैं TRUE ~ ..., जैसे मैंने अपने उदाहरण में किया है, तो वापसी मूल्य कभी नहीं होगा NA

इसलिए, आपको स्पष्ट रूप से यह बताना case_whenहोगा NAकि यह कथन जैसा जोड़कर कहां है is.na(x$V1) | is.na(x$V3) ~ NA_integer_। संकेत: dplyr::coalesce()फ़ंक्शन कभी-कभी यहां उपयोगी हो सकता है!

इसके अलावा, कृपया ध्यान दें कि NAअकेले आम तौर पर काम नहीं, तो आप विशेष डाल करना होगा NAमान: NA_integer_, NA_character_या NA_real_


1
यह व्युत्पन्न की तुलना में काफी तेज था।
फेटो 39

12

ऐसा लगता derivedFactorहै कि mosaicपैकेज इसके लिए डिज़ाइन किया गया था। इस उदाहरण में, यह कुछ इस तरह दिखेगा:

library(mosaic)
myfile <- mutate(myfile, V5 = derivedFactor(
    "1" = (V1==1 & V2!=4),
    "2" = (V2==4 & V3!=1),
    .method = "first",
    .default = 0
    ))

(यदि आप चाहते हैं कि परिणाम एक कारक के बजाय संख्यात्मक हो, तो derivedFactorएक के साथ लपेटें as.numeric)

ध्यान दें कि .defaultविकल्प के साथ संयुक्त विकल्प .method = "first""और" स्थिति सेट करता है - यह दृष्टिकोण के लिए मदद फ़ाइल में वर्णित है derivedFactor


आप .asFactor = Fविकल्प का उपयोग करके या derivedVariableउसी पैकेज में (समान) फ़ंक्शन का उपयोग करके कारक होने से भी रोक सकते हैं ।
जेक फिशर

ऐसा लगता है कि recodedplyr से 0.5 यह करेगा। मैंने इसकी जांच अभी तक नहीं की है। ब्लॉग
जेक फिशर

यह 1e6 पंक्तियों के साथ मेरे डेटा के लिए धीमा था।
फतो 39

3
@ Fato39 हाँ, mosaic::derivedFactorफ़ंक्शंस का परिवार बहुत धीमा है। यदि आपको पता है कि क्यों, कृपया इसके बारे में मेरे SO प्रश्न का उत्तर दें: stackoverflow.com/questions/33787691/… । मुझे आपकी अन्य टिप्पणी से यह देखकर खुशी हुई कि dplyr::case_whenमैं और तेज हूं - मुझे उस पर स्विच करना होगा।
जेक फिशर

मैं निम्नलिखित कमांड, लाइब्रेरी (मोज़ेक) VENEZ.FINAL2 <- म्यूट (VENEZ, SEX = व्युत्पन्न) ("M" = (CATEGORY == "बैल" & CATEGORY! = = SIRE ")," F "= ( CATEGORY == "COW" & CATEGORY! = "HEIFER"), .method = "पहला", .default = "NA")) लेकिन यह काम नहीं करता है, बस VENEZ को हल करें। FINALZ <- mutate (VENEZ,) SEX = व्युत्पन्न ("M" = (CATEGORY ==) "क्या आप मेरी मदद कर सकते हैं? बहुत बहुत धन्यवाद!
जोहाना रामिरेज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.