Biểu đồ đường có quá nhiều dòng, có giải pháp nào tốt hơn không?


30

Tôi đang cố gắng vẽ biểu đồ số lượng hành động của người dùng (trong trường hợp này là "lượt thích") theo thời gian.

Vì vậy, tôi có "Số hành động" là trục y, trục x của tôi là thời gian (tuần) và mỗi dòng đại diện cho một người dùng.

Vấn đề của tôi là tôi muốn xem dữ liệu này cho một bộ khoảng 100 người dùng. Một biểu đồ đường nhanh chóng trở thành một mớ hỗn độn với 100 dòng. Có loại biểu đồ nào tốt hơn mà tôi có thể sử dụng để hiển thị thông tin này không? Hoặc tôi nên xem xét việc có thể bật / tắt các dòng riêng lẻ không?

Tôi muốn xem tất cả dữ liệu cùng một lúc, nhưng có thể nhận ra số lượng hành động với độ chính xác cao không quan trọng lắm.

Tại sao tôi làm điều này

Đối với một tập hợp con của người dùng của tôi (người dùng hàng đầu), tôi muốn tìm ra phiên bản nào có thể không thích phiên bản mới của ứng dụng được tung ra vào một ngày nhất định. Tôi đang tìm kiếm giảm đáng kể số lượng hành động của người dùng cá nhân.


5
Bạn đã xem xét làm cho các dòng bán trong suốt bằng cách thay đổi alpha đang được sử dụng để vẽ chúng chưa?
Fomite

1
@EpiGrad Gợi ý hợp lý nhưng điều đó thực sự sẽ không dễ dàng hơn để xem những gì tôi đang tìm kiếm.
điều chỉnh

1
@regulatethis Tôi sẽ đề xuất cách tiếp cận "nhiều bội số" bằng cách sử dụng facet_wrapchức năng của ggplot2 để tạo một khối 4 x 5 biểu đồ (4 hàng, 5 cột - điều chỉnh tùy theo tỷ lệ khung hình mong muốn) với ~ 5 người dùng trên mỗi biểu đồ. Điều đó đủ rõ ràng và bạn có thể mở rộng tối đa khoảng 10 người dùng trên mỗi biểu đồ, nhường chỗ cho 200 với lô 4x5 hoặc 360 với lô 6x6.
SlowLearner

Câu trả lời:


31

Tôi muốn đề xuất phân tích sơ bộ (tiêu chuẩn) để loại bỏ các tác động chính của (a) biến thể giữa các người dùng, (b) phản ứng điển hình giữa tất cả người dùng đối với thay đổi và (c) biến đổi điển hình từ một khoảng thời gian tiếp theo .

Một cách đơn giản (nhưng không có nghĩa là tốt nhất) để thực hiện việc này là thực hiện một vài lần lặp lại "đánh bóng trung bình" trên dữ liệu để quét trung bình người dùng và trung bình khoảng thời gian, sau đó làm mịn phần dư theo thời gian. Xác định độ mượt mà thay đổi rất nhiều: họ là người dùng bạn muốn nhấn mạnh trong đồ họa.

Vì đây là dữ liệu đếm, nên thể hiện lại chúng bằng cách sử dụng căn bậc hai.

Ví dụ về những gì có thể dẫn đến, đây là bộ dữ liệu mô phỏng 60 tuần gồm 240 người dùng thường thực hiện 10 đến 20 hành động mỗi tuần. Một sự thay đổi trong tất cả người dùng đã xảy ra sau tuần 40. Ba trong số này đã được "bảo" phản ứng tiêu cực với thay đổi. Biểu đồ bên trái hiển thị dữ liệu thô: số lượng hành động của người dùng (với người dùng được phân biệt bằng màu sắc) theo thời gian. Như đã khẳng định trong câu hỏi, đó là một mớ hỗn độn. Biểu đồ bên phải hiển thị kết quả của EDA này - có cùng màu với trước đây - với người dùng phản ứng bất thường được tự động xác định và tô sáng. Việc xác định - mặc dù nó hơi ad hoc - là hoàn chỉnh và chính xác (trong ví dụ này).

Hình 1

Đây là Rmã đã tạo ra những dữ liệu này và tiến hành phân tích. Nó có thể được cải thiện theo nhiều cách, bao gồm

  • Sử dụng một đánh bóng trung bình đầy đủ để tìm phần dư, thay vì chỉ một lần lặp.

  • Làm mịn phần dư riêng trước và sau điểm thay đổi.

  • Có lẽ sử dụng một thuật toán phát hiện ngoại lệ tinh vi hơn. Cái hiện tại chỉ đơn thuần gắn cờ tất cả người dùng có phạm vi dư nhiều hơn hai lần phạm vi trung bình. Mặc dù đơn giản, nó mạnh mẽ và dường như hoạt động tốt. (Giá trị thresholdcó thể đặt của người dùng , có thể được điều chỉnh để làm cho nhận dạng này ít nhiều nghiêm ngặt hơn.)

Tuy nhiên, thử nghiệm cho thấy giải pháp này hoạt động tốt đối với nhiều loại người dùng, từ 12 - 240 trở lên.

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")

3
Đối với hơn 100-200 người dùng, tôi sẽ tăng thresholdlên khoảng để tránh các kết quả dương tính giả. Ví dụ: thử mã với , (đó là một tỷ lệ lớn!) Và . 2.5n.users <- 500n.outliers <- 100threshold <- 2.5
whuber

16

Nói chung, tôi tìm thấy nhiều hơn hai hoặc ba dòng trên một khía cạnh của một cốt truyện bắt đầu khó đọc (mặc dù tôi vẫn làm điều đó mọi lúc). Vì vậy, đây là một ví dụ thú vị về những việc cần làm khi bạn có thứ gì đó về mặt khái niệm có thể là cốt truyện 100 mặt. Một cách có thể là vẽ tất cả 100 khía cạnh nhưng thay vì cố gắng đưa tất cả chúng trên trang cùng một lúc, hãy nhìn vào chúng cùng một lúc trong một hình ảnh động.

Chúng tôi thực sự đã sử dụng kỹ thuật này trong công việc của mình - ban đầu chúng tôi đã tạo hoạt hình hiển thị 60 sơ đồ đường khác nhau làm nền cho một sự kiện (ra mắt chuỗi dữ liệu mới), sau đó thấy rằng chúng tôi thực sự đã chọn một số tính năng của dữ liệu không thể nhìn thấy trong các ô mặt với 15 hoặc 30 mặt trên mỗi trang.

Vì vậy, đây là một cách khác để trình bày dữ liệu thô, trước khi bạn bắt đầu xóa người dùng và các hiệu ứng thời gian điển hình theo khuyến nghị của @whuber. Điều này được trình bày giống như một giải pháp thay thế bổ sung cho phần trình bày dữ liệu thô của anh ấy - Tôi hoàn toàn khuyên bạn sau đó tiến hành phân tích dọc theo các dòng như những gì anh ấy đề xuất.

Một cách để khắc phục vấn đề này là tạo ra các chuỗi thời gian 100 (hoặc 240 trong ví dụ @ whuber) riêng rẽ và đan chúng lại với nhau thành một hình ảnh động. Mã dưới đây sẽ tạo ra 240 hình ảnh riêng biệt thuộc loại này và sau đó bạn có thể sử dụng phần mềm làm phim miễn phí để biến nó thành phim. Thật không may, cách duy nhất tôi có thể làm điều này và giữ chất lượng chấp nhận được là một tệp 9 MB, nhưng nếu bạn không cần gửi nó qua internet thì đó có thể không phải là vấn đề và dù sao tôi cũng chắc chắn có nhiều cách hơn thế hiểu biết hoạt hình. Gói hoạt hình trong R có thể hữu ích ở đây (cho phép bạn thực hiện tất cả trong một cuộc gọi từ R) nhưng tôi đã giữ nó đơn giản cho hình minh họa này.

Tôi đã tạo ra hình ảnh động sao cho nó vẽ từng đường màu đen nặng nề sau đó để lại một bóng màu xanh lục bán trong suốt phía sau để mắt có được hình ảnh dần dần của dữ liệu tích lũy. Có cả rủi ro và cơ hội trong việc này - thứ tự mà các dòng được thêm vào sẽ để lại ấn tượng khác nhau, vì vậy bạn nên xem xét làm cho nó có ý nghĩa theo một cách nào đó.

Dưới đây là một số ảnh tĩnh từ phim, sử dụng cùng dữ liệu mà @whuber đã tạo: nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

# ---------------------------- Data generation - by @whuber ----------------------------#

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 ----------------------------#

# Alternative presentation of original data 
# 
setwd("eg animation")

for (i in 1:n.users){
    png(paste("line plot", i, ".png"),600,600,res=60)
    plot(c(1,n.periods), c(min(observed), max(observed)), 
        xlab="Time period", ylab="Number of actions", 
        main="Raw data", bty="l", type="n")
    if(i>1){apply(observed[1:i,], 1, function(a) {lines(a, col=rgb(0,100,0,50,maxColorValue=255))})}
    lines(observed[i,], col="black", lwd=2)
    abline(v = i.break, col="Gray")  # Mark the last period before a change
    text(1,60,i)
    dev.off()
}

##
# Then proceed to further analysis eg as set out by @whuber

+1, đây là một ý tưởng hay. Bạn cũng có thể bắt đầu một cửa sổ thiết bị mới sử dụng windows()hoặc quartz(), và sau đó tổ của for()vòng lặp bên trong nó. NB, bạn sẽ cần đặt một Sys.sleep(1)ở dưới cùng của vòng lặp của bạn để bạn thực sự có thể thấy các lần lặp. Tất nhiên, chiến lược này không thực sự lưu tệp phim - bạn chỉ cần chạy lại mỗi lần bạn muốn xem lại.
gung - Phục hồi Monica

+1 Ý tưởng rất hay - Tôi sẽ thử cơ hội tiếp theo tôi nhận được. (GTW, Mathematica , ví dụ, làm cho công việc ngắn tạo và lưu hình ảnh động như vậy.)
whuber

Ý tưởng tuyệt vời - một hình ảnh động dọc theo các dòng này (hoặc mã và dữ liệu để tạo) sẽ tạo ra một phụ lục trực tuyến rất gợi cảm cho một ấn phẩm.
N Brouwer

7

Một trong những điều dễ nhất là một boxplot. Bạn có thể thấy ngay cách trung bình mẫu của bạn di chuyển và những ngày nào có nhiều ngoại lệ nhất.

day <- rep(1:10, 100)
likes <- rpois(1000, 10)
d <- data.frame(day, likes)
library(ggplot2)
qplot(x=day, y=likes, data=d, geom="boxplot", group=day)

nhập mô tả hình ảnh ở đây

Đối với phân tích riêng lẻ, tôi khuyên bạn nên lấy một mẫu ngẫu nhiên nhỏ từ dữ liệu của bạn và phân tích chuỗi thời gian riêng biệt.


1
Giải pháp thú vị, nhưng điều tôi thực sự muốn có thể thấy là "thay đổi" trên cơ sở mỗi người dùng như thế nào. Tôi muốn thấy sự biến động trong hoạt động cho người dùng cá nhân. Đó là lý do tại sao tôi đã chọn một dòng ban đầu, nhưng bây giờ hình dung quá lộn xộn.
Regatethis

tốt, nó thực sự phụ thuộc vào kiểu bạn muốn có thể nhìn thấy trong dữ liệu của bạn, có lẽ nếu bạn có thể cho chúng tôi biết bạn đang cố gắng tìm hiểu điều gì, chúng tôi có thể đưa ra giải pháp.
jem77bfp

Đối với một tập hợp con của người dùng của tôi (người dùng hàng đầu), tôi muốn tìm ra phiên bản nào có thể không thích phiên bản mới của ứng dụng được tung ra vào một ngày nhất định. Tôi đang tìm kiếm giảm đáng kể số lượng hành động của người dùng cá nhân.
Regatethis

Chào mừng đến với trang web @ jem77bfp. anh ấy đã nói rằng anh ấy muốn xem tất cả các dữ liệu. Nhưng nó sẽ là tốt đẹp để có thêm chi tiết, tôi đồng ý.
Peter Flom - Tái lập Monica

+1 - thay vì trực quan hóa các ô hộp mặc dù có thể hữu ích để kết nối các thống kê tóm tắt trong biểu đồ đường. Xem câu trả lời này của tôi cho một ví dụ và thảo luận dưới đây.
Andy W

7

Chắc chắn rồi. Đầu tiên, sắp xếp theo số lượng trung bình của hành động. Sau đó thực hiện (giả sử) 4 biểu đồ, mỗi biểu đồ có 25 dòng, một dòng cho mỗi phần tư. Điều đó có nghĩa là bạn có thể thu nhỏ các trục y (nhưng làm cho nhãn trục y rõ ràng). Và với 25 dòng, bạn có thể thay đổi chúng theo loại đường và màu sắc và có thể vẽ biểu tượng và có được sự rõ ràng

Sau đó xếp các đồ thị theo chiều dọc với một trục thời gian duy nhất.

Điều này sẽ khá dễ dàng trong R hoặc SAS (ít nhất là nếu bạn có câu 9 của SAS).


2
+1 - Tôi sẽ đề xuất thậm chí ít dòng hơn trên mỗi bội số nhỏ! Xem bài viết blog liên quan của tôi về chủ đề và một ví dụ. Sắp xếp cũng là một ý tưởng tuyệt vời và những tiềm năng khác có thể bao gồm giá trị tại đường cơ sở hoặc theo dõi hoặc các biện pháp thay đổi (như độ dốc dương hoặc âm, thay đổi phần trăm, v.v.).
Andy W

Tốt đẹp! Blog cộng đồng là gì? Làm thế nào để một người truy cập hoặc viết cho nó?
Peter Flom - Tái lập Monica

3
vui lòng ghé qua phòng trò chuyện Skewed Distribution để biết chi tiết về cách tham gia blog. Chúng tôi luôn mở cho sự đóng góp nhiều hơn từ các thành viên cộng đồng.
Andy W

0

Tôi thấy rằng khi bạn hết thời gian nếu các tùy chọn liên quan đến loại nếu biểu đồ và cài đặt biểu đồ giới thiệu thời gian thông qua hoạt hình là cách tốt nhất để hiển thị vì nó cho bạn thêm một chiều để làm việc và cho phép bạn hiển thị thêm thông tin theo cách dễ dàng theo dõi . Trọng tâm chính của bạn phải là trải nghiệm người dùng cuối.


Bạn có điều gì trong tâm trí khác với giải pháp mà Peter Ellis đã đăng ở đây không? Nếu vậy, bạn có thể vui lòng giải thích về nó?
whuber

0

Nếu bạn quan tâm nhất đến sự thay đổi cho người dùng cá nhân, có thể đây là một tình huống tốt cho bộ sưu tập Sparklines (như ví dụ này từ The Pudding ):

Ví dụ về biểu đồ thu nhỏ từ pudding.cool

Đây là khá chi tiết, nhưng bạn có thể hiển thị nhiều biểu đồ hơn cùng một lúc bằng cách loại bỏ các nhãn và đơn vị trục.

Nhiều công cụ dữ liệu được tích hợp sẵn ( Microsoft Excel có biểu đồ thu nhỏ ), nhưng tôi đoán bạn muốn kéo gói để xây dựng chúng trong R.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.