मैं विज़ुअलाइज़ेशन के लिए अधिकतर ggplot2
का उपयोग करता हूं। आम तौर पर, मैं साजिश इंटरैक्टिव रूप से (यानी कच्चे ggplot2
कोड जो एनएसई का उपयोग करता है) डिज़ाइन करता है लेकिन अंत में, मैं उस कोड को उस फ़ंक्शन में लपेटता हूं जो को साजिश के लिए डेटा और चर प्राप्त करता है। और यह हमेशा दुःस्वप्न का थोड़ा सा हिस्सा है।एक समारोह के अंदर ggplot2 के लिए आलसी मूल्यांकन
तो, सामान्य स्थितियां इस तरह दिखती हैं। मेरे पास कुछ डेटा है और मैं इसके लिए एक साजिश बना रहा हूं (इस मामले में, का उपयोग करके एक बहुत ही सरल उदाहरण, ggplot2
के साथ आता है mpg डेटासेट)।
library(ggplot2)
data(mpg)
ggplot(data = mpg,
mapping = aes(x = class, y = hwy)) +
geom_boxplot() +
geom_jitter(alpha = 0.1, color = "blue")
और जब मैं साजिश को डिजाइन करने के बाद, मैं आम तौर पर विभिन्न चर या डेटा, आदि के लिए इसका उपयोग करना चाहते तो मैं एक समारोह है कि तर्क के रूप में भूखंड के लिए डेटा और चर प्राप्त करता है बनाने । लेकिन एनएसई के कारण, यह फ़ंक्शन हेडर लिखना जितना आसान नहीं है और फिर कॉपी/पेस्ट करें और फ़ंक्शन तर्कों के लिए चर बदलें। जैसा कि नीचे दिखाया गया है, यह काम नहीं करेगा।
mpg <- mpg
plotfn <- function(data, xvar, yvar){
ggplot(data = data,
mapping = aes(x = xvar, y = yvar)) +
geom_boxplot() +
geom_jitter(alpha = 0.1, color = "blue")
}
plotfn(mpg, class, hwy) # Can't find object
## Don't know how to automatically pick scale for object of type function. Defaulting to continuous.
## Warning: restarting interrupted promise evaluation
## Error in eval(expr, envir, enclos): object 'hwy' not found
plotfn(mpg, "class", "hwy") #
तो मैं (वापस जाने के लिए और उदाहरण के लिए, कोड को ठीक करने, aes
एनएसई का उपयोग करता है के aes_string
intead का उपयोग कर इस उदाहरण यह नहीं बल्कि आसान है में है, लेकिन और अधिक जटिल भूखंडों के लिए , बहुत सारे परिवर्तन और परतों के साथ, यह एक दुःस्वप्न बन जाता है)।
plotfn <- function(data, xvar, yvar){
ggplot(data = data,
mapping = aes_string(x = xvar, y = yvar)) +
geom_boxplot() +
geom_jitter(alpha = 0.1, color = "blue")
}
plotfn(mpg, "class", "hwy") # Now this works
और बात यह है कि मैं बहुत सुविधाजनक एनएसई और भी lazyeval
लगता है। तो मुझे ऐसा कुछ करना पसंद है।
mpg <- mpg
plotfn <- function(data, xvar, yvar){
data_gd <- data.frame(
xvar = lazyeval::lazy_eval(substitute(xvar), data = data),
yvar = lazyeval::lazy_eval(substitute(yvar), data = data))
ggplot(data = data_gd,
mapping = aes(x = xvar, y = yvar)) +
geom_boxplot() +
geom_jitter(alpha = 0.1, color = "blue")
}
plotfn(mpg, class, hwy) # Now this works
plotfn(mpg, "class", "hwy") # This still works
plotfn(NULL, rep(letters[1:4], 250), 1:100) # And even this crazyness works
यह मेरा भूखंड समारोह बहुत लचीलापन देता है। उदाहरण के लिए, आप पास उद्धृत या अनगिनत चर नामों और यहां तक कि डेटा को एक परिवर्तनीय नाम (आलसी मूल्यांकन के दुरुपयोग की तरह) के बजाय पास कर सकते हैं।
लेकिन इसमें एक बड़ी समस्या है। फ़ंक्शन का उपयोग प्रोग्रामेटिक रूप से नहीं किया जा सकता है।
dynamically_changing_xvar <- "class"
plotfn(mpg, dynamically_changing_xvar, hwy)
## Error in eval(expr, envir, enclos): object 'dynamically_changing_xvar' not found
# This does not work, because it never finds the object
# dynamically_changing_xvar in the data, and it does not get evaluated to
# obtain the variable name (class)
तो मैं छोरों का उपयोग नहीं कर सकते हैं (उदाहरण के लिए lapply) चर, या डेटा की विभिन्न संयोजनों के लिए एक ही भूखंड का उत्पादन करने के लिए।
तो मैं आलसी मानक और गैर मानक मूल्यांकन के लिए और भी अधिक का दुरुपयोग, और उन सब गठबंधन करने के लिए प्रयास करने के लिए सोचा था तो मैं दोनों है, लचीलापन ऊपर दिखाए गए और प्रोग्राम के रूप में समारोह का उपयोग करने की क्षमता। मूल रूप से, मैं क्या हर चर के लिए पहले lazy_eval
अभिव्यक्ति को tryCatch
उपयोग करने के लिए है और अगर यह विफल रहता है, पार्स अभिव्यक्ति का मूल्यांकन करने के।
plotfn <- function(data, xvar, yvar){
data_gd <- NULL
data_gd$xvar <- tryCatch(
expr = lazyeval::lazy_eval(substitute(xvar), data = data),
error = function(e) eval(envir = data, expr = parse(text=xvar))
)
data_gd$yvar <- tryCatch(
expr = lazyeval::lazy_eval(substitute(yvar), data = data),
error = function(e) eval(envir = data, expr = parse(text=yvar))
)
ggplot(data = as.data.frame(data_gd),
mapping = aes(x = xvar, y = yvar)) +
geom_boxplot() +
geom_jitter(alpha = 0.1, color = "blue")
}
plotfn(mpg, class, hwy) # Now this works, again
plotfn(mpg, "class", "hwy") # This still works, again
plotfn(NULL, rep(letters[1:4], 250), 1:100) # And this crazyness still works
# And now, I can also pass a local variable to the function, that contains
# the name of the variable that I want to plot
dynamically_changing_xvar <- "class"
plotfn(mpg, dynamically_changing_xvar, hwy)
तो, ऊपर उल्लिखित लचीलापन के अलावा, अब मैं एक लाइनर या तो उपयोग कर सकते हैं, विभिन्न चर (या डेटा) के साथ, एक ही भूखंड के कई निर्माण करने के लिए।
lapply(c("class", "fl", "drv"), FUN = plotfn, yvar = hwy, data = mpg)
## [[1]]
##
## [[2]]
##
## [[3]]
भले ही यह बहुत ही व्यावहारिक है, मुझे लगता है यह अच्छा अभ्यास नहीं है। लेकिन यह कितना बुरा अभ्यास है? यह मेरा मुख्य सवाल है। अन्य विकल्प क्या मैं दोनों दुनिया के सर्वश्रेष्ठ होने के लिए उपयोग कर सकता हूं?
, मैं देख सकता इस पद्धति समस्या पैदा कर सकता है। उदाहरण के लिए।
# If I have a variable in the global environment that contains the variable
# I want to plot, but whose name is in the data passed to the function,
# then it will use the name of the variable and not its content
drv <- "class"
plotfn(mpg, drv, hwy) # Here xvar on the plot is drv and not class
और कुछ (कई?) अन्य समस्याओं। लेकिन मुझे लगता है कि वाक्य रचना-लचीलेपन का संदर्भ में लाभ उन अन्य मुद्दों पल्ला झुकना। इस पर कोई विचार?
सबसे अच्छा अभ्यास कार्यों की एक जोड़ी का उत्पादन करना है। एक एनएसई, दूसरा एसई है। यह 'विग्नेट ('एनएसई') में उल्लिखित है। इसका मतलब 'एईएस 'के बजाय' aes_' का उपयोग करना है। – Axeman
धन्यवाद, ..., हाँ, मुझे डर था कि जवाब होने वाला था। हालांकि मैं dplyr और सह के लाभ देखता हूं। "लगातार नामकरण योजना: एसई अंत में _ के साथ एनएसई नाम है", यह हमेशा प्रोग्रामिंग के लिए एक अलग फ़ंक्शन का उपयोग करने और इंटरैक्टिव रूप से काम करने के लिए मुझे बग करता है। – elikesprogramming