(A) kullanıcılar arasındaki değişimin temel etkilerini ortadan kaldırmak için (standart) bir ön analiz önermek istiyorum, (b) tüm kullanıcılar arasındaki değişime tipik tepki, ve (c) bir zaman diliminden diğerine tipik değişim .
Bunu yapmanın basit (ancak hiçbir şekilde en iyisi) yolu, kullanıcı medyanlarını ve zaman periyodu medyanlarını süpürmek için veriler üzerinde birkaç "orta cila" yinelemesi yapmak ve sonra artıkları zamanla pürüzsüz hale getirmektir. Değişen pürüzsüzlükleri belirleyin: bunlar grafikte vurgulamak istediğiniz kullanıcılar.
Bunlar sayım verileri olduğundan, bunları karekök kullanarak yeniden ifade etmek iyi bir fikirdir.
Neyin sonuçlanabileceğinin bir örneği olarak, tipik olarak haftada 10 ila 20 işlem gerçekleştiren 240 kullanıcının simüle edilmiş 60 haftalık bir 60 veri kümesidir. Tüm kullanıcılarda bir değişiklik 40. haftadan sonra gerçekleşti. Bunlardan üçünün değişime olumsuz yanıt vermesi "söylendi". Soldaki grafik ham verileri gösterir: zaman içinde kullanıcı tarafından (renkle ayırt edilen kullanıcılar) yapılan işlem sayısı. Soruda iddia edildiği gibi, bu bir karışıklık. Sağdaki grafik, bu EDA'nın sonuçlarını - önceki gibi aynı renklerde - alışılmadık şekilde yanıt veren kullanıcıların otomatik olarak tanımlayıp vurguladıklarını gösterir. Tanımlama - biraz geçici olmasına rağmen - tam ve doğru (bu örnekte).
İşte R
bu verileri üreten ve analizi yapan kod. Dahil olmak üzere, çeşitli şekillerde geliştirilebilir
Kalıntıları bulmak için yalnızca bir yinelemeden ziyade tam bir cila kullanmak.
Değişim noktasından önce ve sonra artıkları ayrı ayrı yumuşatın.
Belki daha karmaşık bir dış hat tespit algoritması kullanıyor olabilirsiniz. Mevcut olan, yalnızca artık aralıkları medyan aralığın iki katından fazla olan tüm kullanıcıları işaretler. Basit de olsa, sağlam ve iyi çalışıyor gibi görünüyor. (Kullanıcı tarafından ayarlanabilen bir değer,threshold
bu kimliği daha az veya daha katı yapmak için ayarlanabilir.)
Yine de test yapmak, bu çözümün 12 - 240 veya daha fazla kullanıcı sayısında çok işe yaradığını gösteriyor.
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")