R Language
* कार्यों के परिवार को लागू करें (कार्य)
खोज…
टिप्पणियों
*apply
परिवार में एक समारोह एक लूप के for
एक अमूर्त है। छोरों के for
तुलना में *apply
कार्यों के निम्नलिखित फायदे हैं:
- लिखने के लिए कम कोड की आवश्यकता होती है।
- एक पुनरावृत्ति काउंटर नहीं है।
- मध्यवर्ती परिणामों को संग्रहीत करने के लिए अस्थायी चर का उपयोग नहीं करता है।
हालांकि for
छोरों अधिक सामान्य होते हैं और हमें और अधिक जटिल गणनाओं कि हमेशा का उपयोग कर ऐसा करने के लिए तुच्छ नहीं हैं को प्राप्त करने के लिए अनुमति नियंत्रण दे सकते हैं *apply
कार्य करता है।
लूप्स के for
संबंध और *apply
कार्यों को *apply
के for
छोरों के for
प्रलेखन में समझाया गया है।
*apply
सदस्य परिवार को *apply
फ़ंक्शंस के *apply
परिवार में एक ही सिद्धांत के कई प्रकार होते हैं जो मुख्य रूप से उस तरह के आउटपुट पर आधारित होते हैं जो वे वापस करते हैं।
समारोह | इनपुट | उत्पादन |
---|---|---|
apply | matrix , data.frame , या array | वेक्टर या मैट्रिक्स (लौटे प्रत्येक तत्व की लंबाई के आधार पर) |
sapply | वेक्टर या list | वेक्टर या मैट्रिक्स (लौटे प्रत्येक तत्व की लंबाई के आधार पर) |
lapply | वेक्टर या list | list |
vapply | वेक्टर या `सूची | उपयोगकर्ता द्वारा निर्दिष्ट वर्ग के वेक्टर या मैट्रिक्स (लौटे प्रत्येक तत्व की लंबाई के आधार पर) |
mapply | कई वैक्टर, lists या एक संयोजन | list |
"उदाहरण" देखें कि इनमें से प्रत्येक फ़ंक्शन का उपयोग कैसे किया जाता है।
लागू के साथ अनाम कार्यों का उपयोग करें
किसी सरणी या मैट्रिक्स के मार्जिन पर एक फ़ंक्शन (शायद एक अनाम एक) का मूल्यांकन करने के लिए apply
का उपयोग किया जाता है।
आइए iris
डेटासेट का उपयोग इस विचार को समझने के लिए करें। iris
डेटासेट में 3 प्रजातियों के 150 फूल हैं। आइए देखें कि यह डेटासेट कैसे संरचित है:
> head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
अब, कल्पना कीजिए कि आप इनमें से प्रत्येक चर का मतलब जानना चाहते हैं। इस को हल करने के एक तरीका यह एक का उपयोग हो सकता है for
पाश, लेकिन आर प्रोग्रामर अक्सर का उपयोग करेगी apply
(वजहों, टिप्पणियां देखने के लिए):
> apply(iris[1:4], 2, mean)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
- पहले पैरामीटर में, हम केवल पहले 4 कॉलम को शामिल करने के लिए
iris
को पूरा करते हैं, क्योंकिmean
केवल संख्यात्मक डेटा पर काम करता है। - के दूसरे पैरामीटर मान
2
इंगित करता है कि हम स्तंभ केवल (आर × ग सरणी के दूसरे सबस्क्रिप्ट) पर काम करना चाहते हैं;1
पंक्ति का मतलब देना होगा।
उसी तरह हम अधिक सार्थक मूल्यों की गणना कर सकते हैं:
# standard deviation
apply(iris[1:4], 2, sd)
# variance
apply(iris[1:4], 2, var)
कैविएट : आर में कुछ बिल्ट-इन फ़ंक्शंस हैं जो कॉलम और रो रकम की गणना के लिए बेहतर हैं और इसका मतलब है: colMeans
और rowMeans
।
अब, चलो एक अलग और अधिक सार्थक कार्य करते हैं: आइए केवल उन मानों के लिए माध्य की गणना करें जो 0.5
से बड़े हैं। उसके लिए, हम अपना mean
फ़ंक्शन बनाएंगे।
> our.mean.function <- function(x) { mean(x[x > 0.5]) }
> apply(iris[1:4], 2, our.mean.function)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.665347
( Petal.Width
के मतलब में अंतर पर ध्यान दें)
लेकिन, क्या होगा यदि हम अपने बाकी कोड में इस फ़ंक्शन का उपयोग नहीं करना चाहते हैं? फिर, हम एक अनाम फ़ंक्शन का उपयोग कर सकते हैं, और अपना कोड इस तरह लिख सकते हैं:
apply(iris[1:4], 2, function(x) { mean(x[x > 0.5]) })
इसलिए, जैसा कि हमने देखा है, हम केवल एक लाइन का उपयोग करके डेटासेट के कॉलम या पंक्तियों पर एक ही ऑपरेशन को निष्पादित करने के लिए apply
का उपयोग कर सकते हैं।
चेतावनी: चूंकि apply
रिटर्न निर्दिष्ट समारोह के परिणामों की लंबाई के आधार उत्पादन की बहुत अलग प्रकार के हैं, यह उन मामलों में जहां आप सहभागी काम नहीं कर रहे में सबसे अच्छा विकल्प नहीं हो सकता। अन्य में से कुछ *apply
परिवार के कार्य थोड़ा अधिक पूर्वानुमान योग्य हैं (रिमार्क्स देखें)।
थोक फ़ाइल लोड हो रहा है
बड़ी संख्या में फ़ाइलों के लिए जिन्हें एक समान प्रक्रिया में और अच्छी तरह से संरचित फ़ाइल नामों के साथ संचालित करने की आवश्यकता हो सकती है।
सबसे पहले एक्सेस किए जाने वाले फ़ाइल नामों का एक वेक्टर बनाया जाना चाहिए, इसके लिए कई विकल्प हैं:
paste0()
साथ मैन्युअल रूप से वेक्टर बनानाpaste0()
files <- paste0("file_", 1:100, ".rds")
फ़ाइल प्रकार के लिए regex खोज शब्द के साथ
list.files()
का उपयोग करते हुए, नियमित अभिव्यक्ति ( regex ) के ज्ञान की आवश्यकता होती है यदि उसी प्रकार की अन्य फाइलें निर्देशिका में हों।files <- list.files("./", pattern = "\\.rds$", full.names = TRUE)
जहाँ X
उपयोग की जाने वाली फ़ाइलों के नामकरण के एक वेक्टर का उपयोग किया जाता है।
lapply
एक सूची के तत्व के रूप में प्रत्येक प्रतिक्रिया का उत्पादन करेगा।
readRDS
.rds
फ़ाइलों के लिए विशिष्ट है और प्रक्रिया के आवेदन के आधार पर बदल जाएगा।
my_file_list <- lapply(files, readRDS)
यह आवश्यक रूप से परीक्षण के लिए लूप से अधिक तेज नहीं है, लेकिन सभी फाइलों को स्पष्ट रूप से निर्दिष्ट किए बिना सूची के एक तत्व होने की अनुमति देता है।
अंत में, हमें अक्सर एक साथ कई पैकेज लोड करने की आवश्यकता होती है। यह ट्रिक उन सभी पुस्तकालयों पर library()
लागू करके इसे बहुत आसानी से कर सकती है जिन्हें हम आयात करना चाहते हैं:
lapply(c("jsonlite","stringr","igraph"),library,character.only=TRUE)
कई `data.frames` (` lapply`, `mapply`) का संयोजन
इस अभ्यास में, हम चार बूटस्ट्रैप रैखिक प्रतिगमन मॉडल उत्पन्न करेंगे और इन मॉडलों के सारांश को एक एकल डेटा फ्रेम में संयोजित करेंगे।
library(broom)
#* Create the bootstrap data sets
BootData <- lapply(1:4,
function(i) mtcars[sample(1:nrow(mtcars),
size = nrow(mtcars),
replace = TRUE), ])
#* Fit the models
Models <- lapply(BootData,
function(BD) lm(mpg ~ qsec + wt + factor(am),
data = BD))
#* Tidy the output into a data.frame
Tidied <- lapply(Models,
tidy)
#* Give each element in the Tidied list a name
Tidied <- setNames(Tidied, paste0("Boot", seq_along(Tidied)))
इस बिंदु पर, हम data.frame में नाम सम्मिलित करने के लिए दो दृष्टिकोण ले सकते हैं।
#* Insert the element name into the summary with `lapply`
#* Requires passing the names attribute to `lapply` and referencing `Tidied` within
#* the applied function.
Described_lapply <-
lapply(names(Tidied),
function(nm) cbind(nm, Tidied[[nm]]))
Combined_lapply <- do.call("rbind", Described_lapply)
#* Insert the element name into the summary with `mapply`
#* Allows us to pass the names and the elements as separate arguments.
Described_mapply <-
mapply(
function(nm, dframe) cbind(nm, dframe),
names(Tidied),
Tidied,
SIMPLIFY = FALSE)
Combined_mapply <- do.call("rbind", Described_mapply)
यदि आप magrittr
शैली की पाइप के प्रशंसक हैं, तो आप पूरे कार्य को एक ही श्रृंखला में पूरा कर सकते हैं (हालांकि ऐसा करना समझदारी नहीं हो सकती है यदि आपको किसी मध्यस्थ वस्तु की आवश्यकता है, जैसे कि मॉडल ऑब्जेक्ट्स):
library(magrittr)
library(broom)
Combined <- lapply(1:4,
function(i) mtcars[sample(1:nrow(mtcars),
size = nrow(mtcars),
replace = TRUE), ]) %>%
lapply(function(BD) lm( mpg ~ qsec + wt + factor(am), data = BD)) %>%
lapply(tidy) %>%
setNames(paste0("Boot", seq_along(.))) %>%
mapply(function(nm, dframe) cbind(nm, dframe),
nm = names(.),
dframe = .,
SIMPLIFY = FALSE) %>%
do.call("rbind", .)
अंतर्निहित कार्यों का उपयोग करना
अंतर्निहित कार्य: lapply (), sapply (), और mapply ()
आर बिल्ट-इन फंक्शंस के साथ आता है, जिनमें से शायद सबसे प्रसिद्ध कार्य के परिवार हैं। यहाँ कुछ सबसे आम लागू कार्यों का विवरण दिया गया है:
-
lapply()
= एक सूची को एक तर्क के रूप में लेता है और सूची में निर्दिष्ट फ़ंक्शन को लागू करता है। -
sapply()
एक ही = के रूप मेंlapply()
लेकिन एक वेक्टर या एक मैट्रिक्स के लिए उत्पादन को सरल बनाने के प्रयास किए गए।-
vapply()
का एक संस्करण =sapply()
है, जिसमें उत्पादन वस्तु के प्रकार निर्दिष्ट किया जाना चाहिए।
-
-
mapply()
की तरह =lapply()
लेकिन निर्दिष्ट फ़ंक्शन का इनपुट के रूप में कई वैक्टर पारित कर सकते हैं।sapply()
तरह सरलीकृत किया जा सकता है।-
Map()
mapply()
SIMPLIFY = FALSE
साथmapply()
करने के लिए एक उपनामMap()
है।
-
lapply ()
lapply()
का उपयोग दो अलग-अलग पुनरावृत्तियों के साथ किया जा सकता है:
-
lapply(variable, FUN)
-
lapply(seq_along(variable), FUN)
# Two ways of finding the mean of x
set.seed(1)
df <- data.frame(x = rnorm(25), y = rnorm(25))
lapply(df, mean)
lapply(seq_along(df), function(x) mean(df[[x]))
sapply ()
sapply()
या तो एक वेक्टर या एक मैट्रिक्स के लिए अपने आउटपुट को हल करने का प्रयास करेगा।
# Two examples to show the different outputs of sapply()
sapply(letters, print) ## produces a vector
x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))
sapply(x, quantile) ## produces a matrix
mapply ()
mapply()
बहुत काम करता है lapply()
को छोड़कर यह कई वैक्टर को इनपुट के रूप में ले सकता है (इसलिए lapply()
लिए m)।
mapply(sum, 1:5, 10:6, 3) # 3 will be "recycled" by mapply
उपयोगकर्ता द्वारा परिभाषित क्रियाओं का उपयोग करना
उपयोगकर्ता-परिभाषित फ़ंक्शंस
उपयोगकर्ता जटिलता की डिग्री बदलती के लिए अपने स्वयं के कार्य कर सकते हैं। Hadley Wickham द्वारा निम्नलिखित उदाहरण कार्यात्मक हैं:
randomise <- function(f) f(runif(1e3))
lapply2 <- function(x, f, ...) {
out <- vector("list", length(x))
for (i in seq_along(x)) {
out[[i]] <- f(x[[i]], ...)
}
out
}
पहले मामले में, randomise
एकल तर्क f
स्वीकार करता है, और इसे यूनिफ़ॉर्म यादृच्छिक चर के नमूने पर कहता है। तुल्यता प्रदर्शित करने के लिए, हम नीचे set.seed
कहते हैं:
set.seed(123)
randomise(mean)
#[1] 0.4972778
set.seed(123)
mean(runif(1e3))
#[1] 0.4972778
set.seed(123)
randomise(max)
#[1] 0.9994045
set.seed(123)
max(runif(1e3))
#[1] 0.9994045
दूसरा उदाहरण base::lapply
का पुन: कार्यान्वयन है base::lapply
, जो किसी सूची ( x
) में प्रत्येक तत्व के लिए एक ऑपरेशन ( f
) लागू करने के लिए कार्यात्मक का उपयोग करता है। ...
पैरामीटर के लिए अतिरिक्त तर्क पारित करने के लिए अनुमति देता है f
जैसे, na.rm
में विकल्प mean
समारोह:
lapply(list(c(1, 3, 5), c(2, NA, 6)), mean)
# [[1]]
# [1] 3
#
# [[2]]
# [1] NA
lapply2(list(c(1, 3, 5), c(2, NA, 6)), mean)
# [[1]]
# [1] 3
#
# [[2]]
# [1] NA
lapply(list(c(1, 3, 5), c(2, NA, 6)), mean, na.rm = TRUE)
# [[1]]
# [1] 3
#
# [[2]]
# [1] 4
lapply2(list(c(1, 3, 5), c(2, NA, 6)), mean, na.rm = TRUE)
# [[1]]
# [1] 3
#
# [[2]]
# [1] 4