एक समाधान mice
पैकेज के लिए अपने स्वयं के कस्टम इंप्यूटेशन फ़ंक्शन लिखना है । पैकेज इसके लिए तैयार है और सेटअप आश्चर्यजनक रूप से दर्द मुक्त है।
पहले हम सुझाए गए अनुसार डेटा सेटअप करते हैं:
dat=data.frame(x1=c(21, 50, 31, 15, 36, 82, 14, 14, 19, 18, 16, 36, 583, NA,NA,NA, 50, 52, 26, 24),
x2=c(0, NA, 18,0, 19, 0, NA, 0, 0, 0, 0, 0, 0,NA,NA, NA, 22, NA, 0, 0),
x3=c(0, 0, 0, 0, 0, 54, 0 ,0, 0, 0, 0, 0, 0, NA, NA, NA, NA, 0, 0, 0))
अगला हम mice
पैकेज को लोड करते हैं और देखते हैं कि यह डिफ़ॉल्ट रूप से क्या तरीके चुनता है:
library(mice)
# Do a non-imputation
imp_base <- mice(dat, m=0, maxit = 0)
# Find the methods that mice chooses
imp_base$method
# Returns: "pmm" "pmm" "pmm"
# Look at the imputation matrix
imp_base$predictorMatrix
# Returns:
# x1 x2 x3
#x1 0 1 1
#x2 1 0 1
#x3 1 1 0
pmm
के लिए खड़ा है भविष्य कहनेवाला मतलब मिलान सतत चर imputing के लिए शायद सबसे लोकप्रिय इलज़ाम एल्गोरिथ्म -। यह प्रतिगमन मॉडल का उपयोग करके अनुमानित मूल्य की गणना करता है और भविष्यवाणी मूल्य ( यूक्लिडियन दूरी द्वारा ) के लिए 5 निकटतम तत्वों को चुनता है । इन चुने हुए तत्वों को दाता पूल कहा जाता है और अंतिम मूल्य को इस दाता पूल से यादृच्छिक पर चुना जाता है।
भविष्यवाणी मैट्रिक्स से हमें पता चलता है कि विधियां वैरिएबल को पास कर देती हैं जो प्रतिबंधों के लिए रुचि रखते हैं। ध्यान दें कि पंक्ति लक्ष्य चर है और भविष्यवक्ता स्तंभ हैं। यदि x3 कॉलम में X1 में 1 नहीं होता है तो हमें इसे मैट्रिक्स में जोड़ना होगा:imp_base$predictorMatrix["x1","x3"] <- 1
अब मज़े की बात यह है कि इंप्यूटेशन मेथड जेनरेट करते हैं। मैंने यहाँ एक बिलकुल कच्चा तरीका चुना है जहाँ मैं सभी मानों को छोड़ देता हूँ अगर वे मापदंड को पूरा नहीं करते हैं। इसके परिणामस्वरूप लंबे लूप का समय हो सकता है और यह वैध आवेगों को बनाए रखने के लिए संभवतः अधिक कुशल हो सकता है और केवल शेष लोगों को फिर से कर सकता है, हालांकि इसके लिए थोड़ा अधिक ट्विकिंग की आवश्यकता होगी।
# Generate our custom methods
mice.impute.pmm_x1 <-
function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "",
...)
{
max_sum <- sum(max(x[,"x2"], na.rm=TRUE),
max(x[,"x3"], na.rm=TRUE))
repeat{
vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
version = "", ...)
if (all(vals < max_sum)){
break
}
}
return(vals)
}
mice.impute.pmm_x2 <-
function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "",
...)
{
repeat{
vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
version = "", ...)
if (all(vals == 0 | vals >= 14)){
break
}
}
return(vals)
}
mice.impute.pmm_x3 <-
function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "",
...)
{
repeat{
vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
version = "", ...)
if (all(vals == 0 | vals >= 16)){
break
}
}
return(vals)
}
एक बार जब हम उन तरीकों को परिभाषित करते हैं तो हम पिछले तरीकों को बदल देते हैं। यदि आप केवल एकल चर को बदलना चाहते हैं तो आप बस उपयोग कर सकते हैं imp_base$method["x2"] <- "pmm_x2"
लेकिन इस उदाहरण के लिए हम सभी को बदल देंगे (नामकरण आवश्यक नहीं है):
imp_base$method <- c(x1 = "pmm_x1", x2 = "pmm_x2", x3 = "pmm_x3")
# The predictor matrix is not really necessary for this example
# but I use it just to illustrate in case you would like to
# modify it
imp_ds <-
mice(dat,
method = imp_base$method,
predictorMatrix = imp_base$predictorMatrix)
अब तीसरे अभेद्य डेटासेट पर एक नजर डालते हैं:
> complete(imp_ds, action = 3)
x1 x2 x3
1 21 0 0
2 50 19 0
3 31 18 0
4 15 0 0
5 36 19 0
6 82 0 54
7 14 0 0
8 14 0 0
9 19 0 0
10 18 0 0
11 16 0 0
12 36 0 0
13 583 0 0
14 50 22 0
15 52 19 0
16 14 0 0
17 50 22 0
18 52 0 0
19 26 0 0
20 24 0 0
ठीक है, वह काम करता है। मुझे यह समाधान पसंद है क्योंकि आप मुख्यधारा के कार्यों में शीर्ष पर आ सकते हैं और केवल उन प्रतिबंधों को जोड़ सकते हैं जो आपको सार्थक लगते हैं।
अपडेट करें
टिप्पणियों में उल्लिखित कठोर प्रतिबंध @ t0x1n को लागू करने के लिए, हम निम्नलिखित क्षमताओं को रैपर फ़ंक्शन में जोड़ना चाहते हैं:
- छोरों के दौरान मान्य मानों को सहेजें ताकि पिछले से डेटा, आंशिक रूप से सफल रन को खारिज न किया जाए
- अनंत छोरों से बचने के लिए एक भागने तंत्र
- एक उपयुक्त मिलान पाए बिना एक्स बार कोशिश करने के बाद दाता पूल को फुलाएं (यह मुख्य रूप से मम पर लागू होता है)
इसके परिणामस्वरूप थोड़ा अधिक जटिल आवरण कार्य होता है:
mice.impute.pmm_x1_adv <- function (y, ry,
x, donors = 5,
type = 1, ridge = 1e-05,
version = "", ...) {
# The mice:::remove.lindep may remove the parts required for
# the test - in those cases we should escape the test
if (!all(c("x2", "x3") %in% colnames(x))){
warning("Could not enforce pmm_x1 due to missing column(s):",
c("x2", "x3")[!c("x2", "x3") %in% colnames(x)])
return(mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
version = "", ...))
}
# Select those missing
max_vals <- rowSums(x[!ry, c("x2", "x3")])
# We will keep saving the valid values in the valid_vals
valid_vals <- rep(NA, length.out = sum(!ry))
# We need a counter in order to avoid an eternal loop
# and for inflating the donor pool if no match is found
cntr <- 0
repeat{
# We should be prepared to increase the donor pool, otherwise
# the criteria may become imposs
donor_inflation <- floor(cntr/10)
vals <- mice.impute.pmm(y, ry, x,
donors = min(5 + donor_inflation, sum(ry)),
type = 1, ridge = 1e-05,
version = "", ...)
# Our criteria check
correct <- vals < max_vals
if (all(!is.na(valid_vals) |
correct)){
valid_vals[correct] <-
vals[correct]
break
}else if (any(is.na(valid_vals) &
correct)){
# Save the new valid values
valid_vals[correct] <-
vals[correct]
}
# An emergency exit to avoid endless loop
cntr <- cntr + 1
if (cntr > 200){
warning("Could not completely enforce constraints for ",
sum(is.na(valid_vals)),
" out of ",
length(valid_vals),
" missing elements")
if (all(is.na(valid_vals))){
valid_vals <- vals
}else{
valid_vals[is.na(valid_vals)] <-
vals[is.na(valid_vals)]
}
break
}
}
return(valid_vals)
}
ध्यान दें कि यह उस तरह का प्रदर्शन नहीं करता है, सबसे अधिक संभावना है कि सुझाए गए डेटा सेट के कारण सभी मामलों की कमी के बिना गायब हो जाता है। इससे पहले कि मैं भी व्यवहार करना शुरू करूं, मुझे लूप की लंबाई 400-500 तक बढ़ानी होगी। मेरा मानना है कि यह अनजाने में है, आपके इंप्यूटेशन की नकल करना चाहिए कि वास्तविक डेटा कैसे उत्पन्न होता है।
अनुकूलन
इस तर्क ry
में गैर-लापता मूल्य शामिल हैं और हम संभवतः उन तत्वों को हटाकर लूप को तेज कर सकते हैं जिन्हें हमने योग्य प्रतिरूपण पाया है, लेकिन जैसा कि मैं आंतरिक कार्यों से अपरिचित हूं, मैंने इससे परहेज किया है।
मुझे लगता है कि सबसे महत्वपूर्ण बात यह है कि जब आपके पास मजबूत बाधाएं होती हैं, जो आपके भरने के लिए समय लेती हैं, तो आपको अपने आवेगों को समानांतर करना होगा ( क्रॉसविलेक्टेड पर मेरा जवाब देखें )। अधिकांश के पास आज 4-8 कोर वाले कंप्यूटर हैं और आर केवल डिफ़ॉल्ट रूप से उनमें से एक का उपयोग करता है। समय (लगभग) कोर की संख्या को दोगुना करके आधे में कटा हुआ हो सकता है।
प्रतिनियुक्ति पर लापता पैरामीटर
प्रतिरूपण के x2
समय गायब होने की समस्या के बारे में - चूहों ने वास्तव में कभी भी लापता मूल्यों को नहीं खिलाया x
- data.frame
। चूहों विधि शुरू में कुछ यादृच्छिक मूल्य में भरने के भी शामिल है। इंप्यूटेशन का चेन-पार्ट इस प्रारंभिक मूल्य से प्रभाव को सीमित करता है। यदि आप mice
-function को देखते हैं तो आप इसे इंप्यूटेशन कॉल ( mice:::sampler
-function) से पहले पा सकते हैं :
...
if (method[j] != "") {
for (i in 1:m) {
if (nmis[j] < nrow(data)) {
if (is.null(data.init)) {
imp[[j]][, i] <- mice.impute.sample(y,
ry, ...)
}
else {
imp[[j]][, i] <- data.init[!ry, j]
}
}
else imp[[j]][, i] <- rnorm(nrow(data))
}
}
...
समारोह और चूहों को data.init
आपूर्ति की जा सकती है mice
। चूहों । नमूना एक बुनियादी नमूना प्रक्रिया है।
देखने का क्रम
यदि अनुक्रम का दौरा करना महत्वपूर्ण है, तो आप उस क्रम को निर्दिष्ट कर सकते हैं जिसमें mice
-फंक्शन अशुद्धियों को चलाता है। डिफ़ॉल्ट से है, 1:ncol(data)
लेकिन आप अपनी visitSequence
पसंद के अनुसार कुछ भी सेट कर सकते हैं।
0 or 16 or >= 16
से बदल दिया0 or >= 16
जब>=16
से मूल्य शामिल है16
। आशा है कि अपने अर्थ गड़बड़ नहीं किया। उसी के लिए0 or 14 or >= 14