म्यूटेट के दाएं-बाएं भाग में टिडेवल आधारित गैर-मानक मूल्यांकन का उपयोग


13

एक तिगुने पर विचार करें जहां प्रत्येक स्तंभ एक वर्ण वेक्टर है जो कई मान ले सकता है - चलो "एफ" के माध्यम से "ए" कहते हैं।

library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))

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

इसे करने के कई तरीके हैं। लेकिन मुझे यह समझने में दिलचस्पी है कि सबसे अच्छा मुहावरेदार tidy_eval / tidyverse दृष्टिकोण क्या होगा। सबसे पहले, प्रश्न नाम एक म्यूट क्रिया के बाएं हाथ पर होना चाहिए, इसलिए हम उचित रूप से !!और :=ऑपरेटरों का उपयोग करते हैं । लेकिन फिर, दाहिने हाथ की तरफ क्या रखा जाए?

fix_question <- function(df, question) {
    df %>% mutate(!!question := recode(... something goes here...))
}

fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")

मेरा प्रारंभिक विचार था कि यह काम करेगा:

df %>% mutate(!!question := recode(!!question, "A" = NA_character_))

लेकिन निश्चित रूप से समारोह के अंदर धमाकेदार बैंग सिर्फ शाब्दिक चरित्र स्ट्रिंग (उदाहरण के लिए "q1") देता है। मैंने आधार हाथ [[ऑपरेटर के आधार का उपयोग करके और .dplyr से निर्माण पर भरोसा करते हुए, दाएं हाथ की तरफ डेटा को संदर्भित करने के लिए एक हैकी मार्ग की तरह महसूस करता हुआ समाप्त कर दिया , और यह काम करता है, इसलिए एक अर्थ में मैंने अपनी अंतर्निहित समस्या को हल किया है:

df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))

मुझे ऐसे लोगों से प्रतिक्रिया प्राप्त करने में दिलचस्पी है जो tidyeval में बहुत अच्छे हैं जैसे कि क्या ऐसा करने के लिए अधिक मुहावरेदार तरीका है, इस उम्मीद में कि काम किया उदाहरण देखकर tidyeval फ़ंक्शन की मेरी समझ अधिक आम तौर पर सेट हो जाएगी। कोई विचार?


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

1
इस प्रश्न में कई विचारों को मिलाते हुए, मेरा मानना ​​है कि यह सबसे रसीला संस्करण है जो दोनों q1(प्रतीक) और "q1"(स्ट्रिंग) के साथ काम करता है :df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
आर्टेम सोकोलोव

जवाबों:


6

यहां, दाईं ओर :=, हम symप्रतीक में परिवर्तित करने और फिर मूल्यांकन करने के लिए निर्दिष्ट कर सकते हैं ( !!)

fix_question <- function(df, question) {
    df %>%
       mutate(!!question := recode(!! rlang::sym(question), "A" = NA_character_))
  }

fix_question(sample_df, "q1") 
# A tibble: 3 x 2
#  q1    q2   
#  <chr> <chr>
#1 <NA>  B    
#2 B     B    
#3 C     A    

एक बेहतर दृष्टिकोण जो उद्धृत और निर्विवाद इनपुट दोनों के लिए काम करेगा ensym

fix_question <- function(df, question) {
    question <- ensym(question)
    df %>%
       mutate(!!question := recode(!! question, "A" = NA_character_))
  }


fix_question(sample_df, q1)
# A tibble: 3 x 2
#  q1    q2   
#  <chr> <chr>
#1 <NA>  B    
#2 B     B    
#3 C     A    

fix_question(sample_df, "q1")
# A tibble: 3 x 2
#  q1    q2   
#  <chr> <chr>
#1 <NA>  B    
#2 B     B    
#3 C     A    

2
मैंने कुछ रैलिंग रूपांतरण कार्यों के साथ चारों ओर लगाने की कोशिश की थी, लेकिन स्पष्ट रूप से सही का चयन नहीं किया था, लेकिन आपका दृष्टिकोण काम करता है - मुझे लगता है कि मुझे वास्तव में मेरे सिर में टाइप रूपांतरणों को वर्कआउट करने की आवश्यकता है। मेरा !! प्रश्न काम नहीं करता है क्योंकि यह अक्षर स्ट्रिंग का शाब्दिक मूल्यांकन करता है। तुम्हारा काम करता है क्योंकि यह पहली बार चरित्र स्ट्रिंग को एक प्रतीक में परिवर्तित करता है, और फिर प्रतीक का मूल्यांकन करता है, वेक्टर को लौटाता है। मैं सिर्फ अपना सिर नहीं लपेट सकता था जो कि संचालन का क्रम था। एक बार फिर धन्यवाद।
अरोन

8

आप "घुंघराले घुंघराले" विधि का उपयोग कर सकते हैं यदि आपके पास rlang> = 0.4.0 है

@ Eipi10 के लिए स्पष्टीकरण धन्यवाद:

यह एक चरण में बोली-फिर-अनछुए की दो चरण प्रक्रिया को जोड़ती है, इसलिए {{question}}इसके बराबर है!!enquo(question)

fix_question <- function(df, question){
  df %>% mutate({{question}} := recode({{question}}, A = NA_character_))
}

fix_question(sample_df, q1)
# # A tibble: 3 x 2
#   q1    q2   
#   <chr> <chr>
# 1 NA    B    
# 2 B     B    
# 3 C     A    

ध्यान दें कि ensymदृष्टिकोण के विपरीत , यह चरित्र नामों के साथ काम नहीं करता है। इससे भी बदतर, यह सिर्फ एक त्रुटि देने के बजाय गलत काम करता है।

fix_question(sample_df, 'q1')

# # A tibble: 3 x 2
#   q1    q2   
#   <chr> <chr>
# 1 q1    B    
# 2 q1    B    
# 3 q1    A    

2
मैं "घुंघराले घुंघराले" आदत में अभी तक नहीं मिला है। क्या आप जानते हैं कि यह क्यों काम करता है, जबकि ओपी का प्रतीत होने वाला-समान "बैंग बैंग" संस्करण नहीं था?
कैमिली

घुंघराले-घुंघराले उल्लेख करने के लिए धन्यवाद, जो मैंने सुना था वह आगामी था। मैंने जो भी rlang / dplyr स्थापित किया है, उसके उत्तर के लिए काम नहीं करता है; मुझे LHS के साथ एक त्रुटि मिलती है। यदि मैं अपने LHS के साथ LHS को प्रतिस्थापित करता हूं और q1 को उद्धृत करता हूं, तो मुझे वही समस्या मिलती है जो मेरे पास थी; अगर मैं q1 को उद्धृत नहीं करता हूं, तो मुझे एक त्रुटि मिलती है। यह संभवतः एक संस्करण बात है।
ऐरन

1
हाँ रलंग 0.4.0 अभी जून के अंत में जारी किया गया था, इसलिए यदि आपने इसे अपडेट नहीं किया है तो यह आपके लिए काम नहीं करेगा
IceCreamToucan

2
मुझे लगता है कि बैंग-बैंग काम नहीं करता था, क्योंकि questionपहले question = enquo(question)dplyr पाइप में उपयोग किए जाने से पहले एक क्वॉजिट ( ) में बदलना पड़ता है। {{question}}के बराबर है !!enquo(question)
eipi10 17

2
समकक्ष होने के लिए आपको प्रश्न के पहले उदाहरण के लिए भी enquo की आवश्यकता है।
आइसक्रिम्सटाकन

7

आप पुनरावर्ती मानों के एक वेक्टर को एक तर्क के रूप में दर्ज करने की अनुमति देकर फ़ंक्शन को थोड़ा अधिक लचीला बना सकते हैं। उदाहरण के लिए:

library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))

fix_question <- function(df, question, recode.vec) {

  df %>% mutate({{question}} := recode({{question}}, !!!recode.vec))

}

fix_question(sample_df, q1, c(A=NA_character_, B="Was B"))
  q1    q2   
1 <NA>  B    
2 Was B B    
3 C     A

ध्यान दें कि recode.vec"unquote-spliced" के साथ है !!!। आप यह देख सकते हैं कि यह इस उदाहरण के साथ क्या कर रहा है, despr विगनेट के साथ प्रोग्रामिंग से अनुकूलित (प्रासंगिक उदाहरणों को देखने के लिए "ब्याह" के लिए खोज)। ध्यान दें कि फ़ंक्शन !!!में रिकोडिंग मानों के जोड़े "स्पाइस" कैसे recodeकरते हैं ताकि उनका उपयोग ...तर्क के रूप में किया जाए recode

x = c("A", "B", "C")
args = c(A=NA_character_, B="Was B")

quo(recode(x, !!!args))

<quosure>
expr: ^recode(x, A = <chr: NA>, B = "Was B")
env:  global

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

fix_question <- function(question, recode.vec) {

  recode({{question}}, !!!recode.vec)

}

sample_df %>% 
  mutate_at(vars(matches("q")), list(~fix_question(., c(A=NA_character_, B="Was B"))))
  q1    q2   
1 <NA>  Was B
2 Was B Was B
3 C     <NA>

या किसी एक कॉलम को रीकोड करने के लिए:

sample_df %>% 
  mutate(q1 = fix_question(q1, c(A=NA_character_, B="Was B")))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.