Milyonlarca puan varken verileri daha verimli bir şekilde çizmek için istatistiksel yöntemler?


31

Milyonlarca puan varken R'nin araziler üretmesinin uzun zaman alabildiğini görüyorum - puanların ayrı ayrı çizilmesi şaşırtıcı değil. Ayrıca, bu tür araziler çoğu zaman fazla dağınıktır ve kullanışlı olması için yoğundur. Noktaların çoğu örtüşür ve siyah bir kütle oluşturur ve bu kütleye daha fazla nokta çizmek için çok zaman harcanır.

Standart bir dağılım grafiğinde büyük verilerini temsil etmenin istatistiksel bir alternatifi var mı? Yoğunluk grafiği olarak düşündüm, fakat başka hangi alternatifler var?n


1
Doğrusal çizimleri olan bazı çözümler için bkz. Stats.stackexchange.com/questions/35220/… .
whuber

Yanıtlar:


13

Bu, hazır çözümler içermeyen zor bir iştir (elbette ki, çünkü yoğunluk grafiği, kimsenin umurunda olmadığı kadar çekici bir geri dönüşdür). Ne yapabilirsin?

Gerçekten örtüşüyorlarsa (yani tam olarak aynı X & Y koordinatlarına sahipse) ve alfa kullanmıyorsanız, en iyi fikir yalnızca üst üste binmeyi azaltmak unique(alfa ile bu tür gruplar üzerinde toplanabilir) olacaktır.

Değilse, koordinatları manuel olarak en yakın piksellere yuvarlayabilir ve önceki yöntemi kullanabilirsiniz (ancak bu kirli bir çözümdür).

Son olarak, en yoğun bölgelerdeki noktaları alt örneklemede kullanmak için bir yoğunluk grafiği yapabilirsiniz. Öte yandan, bu tam olarak aynı arsa yapmaz ve tam olarak ayarlanmadığı takdirde eserler getirebilir.


5
Örtüşmeyi uniqueveya yuvarlama ile örtüşmenin azaltılması, taraflı (aldatıcı) lekelere neden olabilir. Bir şekilde üst üste binme miktarını hafiflik veya ayçiçeği grafikleri gibi bazı grafiksel araçlarla belirtmek önemlidir.
whuber

44

Dan Carr'ın makalesini / yöntemini uygulayan hexbin paketine bakın . Pdf vinyet aşağıda alıntı daha fazla ayrıntı vardır:

1 Genel Bakış

Altıgen bindirme, büyük n'li veri kümelerinde yapıyı görselleştirmek için yararlı bir iki değişkenli histogram şeklidir. Altıgen bindirmenin altında yatan konsept son derece basittir;

  1. setin üzerindeki xy düzlemi (aralık (x), aralık (y)), düzenli bir altıgen ızgarası tarafından mozaikleştirilir.
  2. Her altıgen içine düşen noktaların sayısı bir veri yapısında sayılır ve saklanır
  3. sayım> 0 olan altıgenler, bir renk rampası kullanılarak veya altıgen yarıçapının yarıçapları sayılarla orantılı olarak değiştirilerek çizilir. Temel algoritma, olan veri kümelerinin yapısını görüntülemek için son derece hızlı ve etkilidir.n106

Şebekenin boyutu ve renk rampası içindeki kesikler, verinin doğasında bulunan yapıdan zekice bir şekilde seçilirse, bindirilmiş parsellerde ortaya çıkması gerekir. Aynı uyarılar, histogramlara uygulanan altıgen bindirmeler için de geçerlidir ve binicilik parametrelerinin seçiminde özen gösterilmelidir.


4
Bu iyi bir tane. Sadece doktorun sipariş ettiği şey.
Roman Luštrik

13
(+1) Ayrıca ilgi çekici smoothScatter {RColorBrewer}ve densCols {grDevices}. Genetik verilerden bin milyonlarca puanla oldukça iyi çalıştığını onaylayabilirim.
chl

2
Ya 3B veri varsa? (scatterplot3d için çok fazla)
skan

Başkalarına zaman kazandırmak için - 2 yorum önerildiği gibi smoothScatter'ı daha iyi varsayılanlara / fonksiyonlara sahip olmak için buldum.
Charlie,

16

Son paragrafınızı tam olarak anlamadığımı itiraf etmeliyim:

"Yoğunluk grafiği aramıyorum (bunlar genellikle yararlı olsa da), basit bir arsa çağrısı ile aynı çıktıyı isterdim, ancak mümkünse milyonlarca aşırı noktadan daha hızlı olmasını istiyorum."

Ne tür bir arsa (işlev) aradığınızı da belli değil.

Metrik değişkenleriniz olduğu göz önüne alındığında, altıgen çizgili bindirilmiş alanlar veya sunnflower çizimleri faydalı bulabilirsiniz. Daha fazla referans için, bkz.


6

Soruya doğrudan bir başka cevap OpenGL kullanarak milyonlarca nokta çizebilen rgl paketidir. Ayrıca, bir nokta boyutu (örneğin 3) belirtin ve bu kütle merkezlerini monolitik bloklar olarak görmek için yakınlaştırın veya uzaklaştırın veya monolitik olanın yapısını yakınlaştırın ve yakınlaştırın - nokta boyutları sabittir, ancak bunlar arasındaki mesafeler ekranda yakınlaştırmaya bağlı. Alfa seviyeleri de kullanılabilir.


5

İşte aradığım bir dosya bigplotfix.R. Kaynak yaparsanız plot.xy, çok büyük olduğunda, arsa verilerini "sıkıştıran" bir sarıcı tanımlayacaktır . Sarıcı, giriş küçükse hiçbir şey yapmaz, ancak giriş büyükse, girişleri böler ve her yığın için maksimum ve minimum x ve y değerlerini gösterir. Kaynaklama bigplotfix.Rayrıca graphics::plot.xyambalajı işaret etmek için yeniden bağlanır (birçok kez kaynak yapmak tamamdır).

Not plot.xygibi standart çizim yöntemleri için "beygir" işlevidir plot(), lines()ve points(). Böylelikle bu fonksiyonları kodunuzda hiçbir değişiklik yapmadan kullanmaya devam edebilirsiniz ve büyük arazileriniz otomatik olarak sıkıştırılacaktır.

Bu bazı örnek çıktılar. Esasen plot(runif(1e5)), noktalar ve çizgilerle ve burada "sıkıştırma" uygulanmış olan ve olmayanlar. "Sıkıştırılmış noktalar" grafiği, sıkıştırmanın niteliği nedeniyle orta bölgeyi özlüyor, ancak "sıkıştırılmış çizgiler" grafiği, sıkıştırılmamış orijinaline çok daha yakın görünüyor. Zamanlar png()cihaz içindir; Bazı nedenlerden dolayı, pngcihazda cihazda olduğundan çok daha hızlı X11, ancak hızlananlar X11karşılaştırılabilir ( denemelerimden X11(type="cairo")daha yavaştı X11(type="Xlib")).

"bigplotfix.R" test output

Bunu yazmamın nedeni, plot()büyük bir veri setinde (örneğin bir WAV dosyası) kazayla çalışmaktan yorulmamdı. Bu gibi durumlarda, çizimin bitmesi için birkaç dakika bekleyip R oturumumu bir sinyal ile sonlandırmak arasında seçim yapmak zorunda kalacağım (böylece son komut geçmişimi ve değişkenlerimi kaybedeceğim). Şimdi bu dosyayı her oturumdan önce yüklediğimi hatırlayabilirsem, bu durumlarda gerçekten yararlı bir komplo bulabilirim. Küçük bir uyarı mesajı, arsa verilerinin ne zaman "sıkıştırıldığını" gösterir.

# bigplotfix.R
# 28 Nov 2016

# This file defines a wrapper for plot.xy which checks if the input
# data is longer than a certain maximum limit. If it is, it is
# downsampled before plotting. For 3 million input points, I got
# speed-ups of 10-100x. Note that if you want the output to look the
# same as the "uncompressed" version, you should be drawing lines,
# because the compression involves taking maximum and minimum values
# of blocks of points (try running test_bigplotfix() for a visual
# explanation). Also, no sorting is done on the input points, so
# things could get weird if they are out of order.
test_bigplotfix = function() {
  oldpar=par();
  par(mfrow=c(2,2))
  n=1e5;
  r=runif(n)
  bigplotfix_verbose<<-T
  mytitle=function(t,m) { title(main=sprintf("%s; elapsed=%0.4f s",m,t["elapsed"])) }
  mytime=function(m,e) { t=system.time(e); mytitle(t,m); }

  oldbigplotfix_maxlen = bigplotfix_maxlen
  bigplotfix_maxlen <<- 1e3;

  mytime("Compressed, points",plot(r));
  mytime("Compressed, lines",plot(r,type="l"));
  bigplotfix_maxlen <<- n
  mytime("Uncompressed, points",plot(r));
  mytime("Uncompressed, lines",plot(r,type="l"));
  par(oldpar);
  bigplotfix_maxlen <<- oldbigplotfix_maxlen
  bigplotfix_verbose <<- F
}

bigplotfix_verbose=F

downsample_xy = function(xy, n, xlog=F) {
  msg=if(bigplotfix_verbose) { message } else { function(...) { NULL } }
  msg("Finding range");
  r=range(xy$x);
  msg("Finding breaks");
  if(xlog) {
    breaks=exp(seq(from=log(r[1]),to=log(r[2]),length.out=n))
  } else {
    breaks=seq(from=r[1],to=r[2],length.out=n)
  }
  msg("Calling findInterval");
  ## cuts=cut(xy$x,breaks);
  # findInterval is much faster than cuts!
  cuts = findInterval(xy$x,breaks);
  if(0) {
    msg("In aggregate 1");
    dmax = aggregate(list(x=xy$x, y=xy$y), by=list(cuts=cuts), max)
    dmax$cuts = NULL;
    msg("In aggregate 2");
    dmin = aggregate(list(x=xy$x, y=xy$y), by=list(cuts=cuts), min)
    dmin$cuts = NULL;
  } else { # use data.table for MUCH faster aggregates
    # (see http://stackoverflow.com/questions/7722493/how-does-one-aggregate-and-summarize-data-quickly)
    suppressMessages(library(data.table))
    msg("In data.table");
    dt = data.table(x=xy$x,y=xy$y,cuts=cuts)
    msg("In data.table aggregate 1");
    dmax = dt[,list(x=max(x),y=max(y)),keyby="cuts"]
    dmax$cuts=NULL;
    msg("In data.table aggregate 2");
    dmin = dt[,list(x=min(x),y=min(y)),keyby="cuts"]
    dmin$cuts=NULL;
    #  ans = data_t[,list(A = sum(count), B = mean(count)), by = 'PID,Time,Site']
  }
  msg("In rep, rbind");
  # interleave rows (copied from a SO answer)
  s <- rep(1:n, each = 2) + (0:1) * n
  xy = rbind(dmin,dmax)[s,];
  xy
}

library(graphics);
# make sure we don't create infinite recursion if someone sources
# this file twice
if(!exists("old_plot.xy")) {
  old_plot.xy = graphics::plot.xy
}

bigplotfix_maxlen = 1e4

# formals copied from graphics::plot.xy
my_plot.xy = function(xy, type, pch = par("pch"), lty = par("lty"),
  col = par("col"), bg = NA, cex = 1, lwd = par("lwd"),
  ...) {

  if(bigplotfix_verbose) {
    message("In bigplotfix's plot.xy\n");
  }

  mycall=match.call();
  len=length(xy$x)
  if(len>bigplotfix_maxlen) {
    warning("bigplotfix.R (plot.xy): too many points (",len,"), compressing to ",bigplotfix_maxlen,"\n");
    xy = downsample_xy(xy, bigplotfix_maxlen, xlog=par("xlog"));
    mycall$xy=xy
  }
  mycall[[1]]=as.symbol("old_plot.xy");

  eval(mycall,envir=parent.frame());
}

# new binding solution adapted from Henrik Bengtsson
# https://stat.ethz.ch/pipermail/r-help/2008-August/171217.html
rebindPackageVar = function(pkg, name, new) {
  # assignInNamespace() no longer works here, thanks nannies
  ns=asNamespace(pkg)
  unlockBinding(name,ns)
  assign(name,new,envir=asNamespace(pkg),inherits=F)
  assign(name,new,envir=globalenv())
  lockBinding(name,ns)
}
rebindPackageVar("graphics", "plot.xy", my_plot.xy);

0

Belki benim yöntemimden mahrum kalacağım, araştırmalarımdan birinin kötü hatıraları, insanları kategorilere çevirerek iyi verileri çöpe atmak için çığlık atıyor. Her neyse, eğer bir dağılım grafiğinden bahsediyorsan, o zaman aynı sorunları yaşadım. Şimdi, sayısal verilere sahip olduğumda, analiz için kategorize etmem çok anlamlı değil. Ancak görselleştirme farklı bir hikaye. Benim için en iyi olanı bulduğum şey, öncelikle (1) bağımsız değişkeninizi cut işlevini kullanarak gruplara ayırmak. Grupların sayısı ile oynayabilir ve daha sonra (2) sadece DV'yi IV'ün kesilmiş versiyonuna karşı çizerek yapabilirsiniz. R, iğrenç saçılma grafiği yerine kutu grafikleri üretecektir. Aykırı değerlerin arsadan kaldırılmasını tavsiye ederim (arsa komutunda outline = FALSE seçeneğini kullanın). Yine, ASLA kategorize ederek ve sonra analiz ederek tamamen iyi bir sayısal veriyi israf etmem. Bunu yaparken çok fazla sorun var. Her ne kadar bunun çok hassas bir tartışma konusu olduğunu biliyorum. Ama bunu özellikle verilerden en azından bir miktar görsel anlam çıkarmak amacıyla yapmak, ondan gördüğüm zararı değil. Verileri 10 milyon kadar büyük bir alana çizdim ve hala bu yöntemden anlam çıkarmayı başardım. Umarım yardımcı olur! Saygılarımla! ondan gördüm. Verileri 10 milyon kadar büyük bir alana çizdim ve hala bu yöntemden anlam çıkarmayı başardım. Umarım yardımcı olur! Saygılarımla! ondan gördüm. Verileri 10 milyon kadar büyük bir alana çizdim ve hala bu yöntemden anlam çıkarmayı başardım. Umarım yardımcı olur! Saygılarımla!


0

Büyük zaman serileri için, smoothScatter'ı sevmeye başlamıştım (R tabanının bir kısmı değil). Sık sık bazı ek veriler eklemeliyim ve temel komplo API'sini korumak gerçekten yardımcı oluyor, örneğin:

set.seed(1)
ra <- rnorm(n = 100000, sd = 1, mean = 0)
smoothScatter(ra)
abline(v=25000, col=2)
text(25000, 0, "Event 1", col=2)

Hangisi size verirse (eğer tasarımı affederseniz)

scatterSmooth example

Her zaman kullanılabilir ve devasa veri kümeleriyle iyi çalışıyor, bu nedenle en azından sahip olduğunuza bir göz atmak güzel.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.