मैं (a) उपयोगकर्ताओं के बीच (a) भिन्नता के मुख्य प्रभावों को हटाने के लिए (मानक) प्रारंभिक विश्लेषण का सुझाव देना चाहूंगा, (b) परिवर्तन के लिए सभी उपयोगकर्ताओं के बीच विशिष्ट प्रतिक्रिया, और (c) एक समय अवधि से अगली अवधि तक विशिष्ट बदलाव ।
ऐसा करने के लिए एक सरल (लेकिन किसी भी तरह से सबसे अच्छा) तरीका उपयोगकर्ता मध्यस्थों और समय अवधि के मध्यस्थों को बाहर निकालने के लिए डेटा पर "माध्यिका पॉलिश" के कुछ पुनरावृत्तियों को करना है, फिर समय के साथ अवशिष्टों को चिकना करना। उन स्मूथियों को पहचानें जो बहुत बदल जाती हैं: वे ऐसे उपयोगकर्ता हैं जिन्हें आप ग्राफ़िक में ज़ोर देना चाहते हैं।
क्योंकि ये गणना डेटा हैं, उन्हें एक वर्गमूल का उपयोग करके फिर से व्यक्त करना एक अच्छा विचार है।
परिणाम क्या हो सकता है, इसके उदाहरण के रूप में, यहां 240 उपयोगकर्ताओं के 60-सप्ताह का डेटासेट है जो आमतौर पर प्रति सप्ताह 10 से 20 कार्रवाई करते हैं। सप्ताह 40 के बाद सभी उपयोगकर्ताओं में परिवर्तन हुआ। इनमें से तीन को "" बताया गया था जो कि परिवर्तन के प्रति नकारात्मक प्रतिक्रिया व्यक्त करते हैं। बायां प्लॉट कच्चे डेटा को दिखाता है: समय के साथ उपयोगकर्ता द्वारा कार्रवाई की गणना (रंग द्वारा प्रतिष्ठित उपयोगकर्ताओं के साथ)। प्रश्न में कहा गया है, यह एक गड़बड़ है। सही प्लॉट इस EDA के परिणामों को पहले के समान रंगों में दिखाता है - असामान्य रूप से उत्तरदायी उपयोगकर्ताओं के साथ स्वचालित रूप से पहचाने और हाइलाइट किए गए। पहचान - यह कुछ हद तक है, हालांकि तदर्थ --is पूर्ण और सही (इस उदाहरण में)।
यहां वह R
कोड है जो इन आंकड़ों का उत्पादन करता है और विश्लेषण करता है। इसमें कई तरीकों से सुधार किया जा सकता है, जिसमें शामिल हैं
केवल एक पुनरावृत्ति के बजाय अवशिष्टों को खोजने के लिए एक पूर्ण माध्यिका पॉलिश का उपयोग करना।
परिवर्तन बिंदु से पहले और बाद में अवशेषों को अलग से चिकना करना।
शायद अधिक परिष्कृत आउटलाइयर डिटेक्शन एल्गोरिदम का उपयोग करना। वर्तमान में केवल उन सभी उपयोगकर्ताओं को झंडे मिलते हैं जिनकी अवशिष्ट की सीमा औसतन दो बार से अधिक होती है। यद्यपि यह सरल है, यह मजबूत है और अच्छी तरह से काम करता है। (उपयोगकर्ता-सेटल करने योग्य मान, threshold
इस पहचान को कम या ज्यादा कठोर बनाने के लिए समायोजित किया जा सकता है।)
फिर भी परीक्षण से पता चलता है कि यह समाधान उपयोगकर्ता की एक विस्तृत श्रृंखला के लिए अच्छी तरह से काम करता है, 12 - 240 या अधिक।
n.users <- 240 # Number of users (here limited to 657, the number of colors)
n.periods <- 60 # Number of time periods
i.break <- 40 # Period after which change occurs
n.outliers <- 3 # Number of greatly changed users
window <- 1/5 # Temporal smoothing window, fraction of total period
response.all <- 1.1 # Overall response to the change
threshold <- 2 # Outlier detection threshold
# Create a simulated dataset
set.seed(17)
base <- exp(rnorm(n.users, log(10), 1/2))
response <- c(rbeta(n.users - n.outliers, 9, 1),
rbeta(n.outliers, 5, 45)) * response.all
actual <- cbind(base %o% rep(1, i.break),
base * response %o% rep(response.all, n.periods-i.break))
observed <- matrix(rpois(n.users * n.periods, actual), nrow=n.users)
# ---------------------------- The analysis begins here ----------------------------#
# Plot the raw data as lines
set.seed(17)
colors = sample(colors(), n.users) # (Use a different method when n.users > 657)
par(mfrow=c(1,2))
plot(c(1,n.periods), c(min(observed), max(observed)), type="n",
xlab="Time period", ylab="Number of actions", main="Raw data")
i <- 0
apply(observed, 1, function(a) {i <<- i+1; lines(a, col=colors[i])})
abline(v = i.break, col="Gray") # Mark the last period before a change
# Analyze the data by time period and user by sweeping out medians and smoothing
x <- sqrt(observed + 1/6) # Re-express the counts
mean.per.period <- apply(x, 2, median)
residuals <- sweep(x, 2, mean.per.period)
mean.per.user <- apply(residuals, 1, median)
residuals <- sweep(residuals, 1, mean.per.user)
smooth <- apply(residuals, 1, lowess, f=window) # Smooth the residuals
smooth.y <- sapply(smooth, function(s) s$y) # Extract the smoothed values
ends <- ceiling(window * n.periods / 4) # Prepare to drop near-end values
range <- apply(smooth.y[-(1:ends), ], 2, function(x) max(x) - min(x))
# Mark the apparent outlying users
thick <- rep(1, n.users)
thick[outliers <- which(range >= threshold * median(range))] <- 3
type <- ifelse(thick==1, 3, 1)
cat(outliers) # Print the outlier identifiers (ideally, the last `n.outliers`)
# Plot the residuals
plot(c(1,n.periods), c(min(smooth.y), max(smooth.y)), type="n",
xlab="Time period", ylab="Smoothed residual root", main="Residuals")
i <- 0
tmp <- lapply(smooth,
function(a) {i <<- i+1; lines(a, lwd=thick[i], lty=type[i], col=colors[i])})
abline(v = i.break, col="Gray")