Статистичні методи для більш ефективного побудови даних при наявності мільйонів балів?


31

Я вважаю, що R може зайняти тривалий час для створення сюжетів, коли присутні мільйони балів - не дивно, враховуючи, що бали розміщуються окремо. Крім того, такі сюжети часто занадто захаращені та щільні, щоб бути корисними. Багато пунктів перекриваються і утворюють чорну масу, і багато часу витрачається, будуючи більше точок на цю масу.

Чи є якісь статистичні альтернативи для представлення великих даних у стандартному розсіювачі? Я розглядав графік щільності, але які інші альтернативи є?н


1
Про деякі рішення з лінійними графіками див. Stats.stackexchange.com/questions/35220/… .
whuber

Відповіді:


13

Це складне завдання без готових рішень (це, звичайно, тому, що графік щільності настільки заманливий запас, ніж нікого насправді не цікавить). Отже, що ти можеш зробити?

Якщо вони дійсно перекриваються (тобто мають абсолютно однакові координати X & Y), а ви не використовуєте альфа, найкращою ідеєю було б просто зменшити накладення unique( використовуючи альфа, це може бути підсумовано для таких груп).

Якщо ні, ви можете вручну округлити координати до найближчих пікселів і скористатися попереднім методом (але це брудне рішення).

Нарешті, ви можете зробити графік щільності лише для того, щоб використовувати його для розбивання точок на найбільш щільних ділянках. Це, з іншого боку, не зробить абсолютно однаковий сюжет і може внести артефакти, якщо не точно налаштовані.


5
Зменшення перекриття за допомогою uniqueабо округлення може призвести до упереджених (оманливих) сюжетів. Важливо якось вказати кількість перекриття за допомогою деяких графічних засобів, таких як легкість або з ділянками соняшника.
whuber

44

Подивіться на хексбіновий пакет, який реалізує папір / метод Дена Карра. У віньетці pdf є більше деталей, які я цитую нижче:

1 Огляд

Шестикутний бінінг - це форма двовимірної гістограми, корисна для візуалізації структури в наборах даних з великим n. Основна концепція шістнадцяткового кодування надзвичайно проста;

  1. площина xy над безліччю (діапазон (x), діапазон (y)) тесселюється звичайною сіткою шестикутників.
  2. кількість точок, що падають у кожному шестикутнику, підраховується та зберігається у структурі даних
  3. н106

Якщо розмір сітки та надрізи в кольоровій рампі обрані розумно, то структура, притаманна даним, повинна з’являтися на бінованих ділянках. Ті ж застереження застосовуються до шестикутника, що застосовується до гістограм, і слід бути обережним при виборі параметрів бінінгу.


4
Це приємне. Тільки те, що призначив лікар.
Роман Луштрик

13
(+1) Також цікаво, smoothScatter {RColorBrewer}і densCols {grDevices}. Я можу підтвердити, що він працює досить добре з тисячами до мільйонів балів від генетичних даних.
chl

2
Що робити, якщо є дані 3D? (занадто багато для
scatterplot3d

Щоб заощадити інших на деякий час - я знайшов smoothScatter, як запропонували 2 коментарі, щоб мати набагато кращі налаштування / функціонування.
Чарлі

16

Я мушу визнати, що я не повністю розумію ваш останній абзац:

"Я не шукаю графіку щільності (хоча вони часто корисні), я б хотів отримати такий самий вихід, як і простий сюжетний дзвінок, але набагато швидше, ніж мільйони перевитрат, якщо це можливо".

Також незрозуміло, який тип сюжету (функції) ви шукаєте.

Враховуючи, що у вас є метричні змінні, ви можете виявити корисні шестикутникові ділянки або соняшникові корисні ділянки. Детальнішу інформацію див


6

Ще одна пряма відповідь на питання - пакет rgl, який може побудувати мільйони очок за допомогою OpenGL. Крім того, вкажіть розмір точки (наприклад, 3) і зменшіть масштаб, щоб побачити ці центри маси як монолітні блоки, або збільшити масштаб і побачити структуру того, що раніше було монолітним - розміри точок постійні, але відстані між ними на екрані залежать від масштабування. Альфа-рівні також можуть бути використані.


5

Ось файл, який я дзвоню bigplotfix.R. Якщо ви його джерелом, він визначить обгортку, для plot.xyякої "стискає" дані ділянки, коли вона дуже велика. Обгортка нічого не робить, якщо вхід малий, але якщо вхід великий, то він розбиває його на шматки і просто накреслює максимальне і мінімальне значення x і y для кожного фрагмента. Sourcing bigplotfix.Rтакож відновлює, graphics::plot.xyщоб вказати на обгортку (джерело кілька разів добре).

Зверніть увагу , що plot.xyфункція «робочої конячки» для стандартних методів ПРОКЛАДКИ , як plot(), lines()і points(). Таким чином, ви можете продовжувати використовувати ці функції у своєму коді без змін, і ваші великі ділянки будуть автоматично стискатися.

Це деякий приклад виводу. Це по суті plot(runif(1e5)), з точками і лініями, з і без "стиснення", реалізованого тут. Сюжет "стислих точок" пропускає середню область через характер стиснення, але сюжет "стислих ліній" виглядає набагато ближче до стисненого оригіналу. Часи для png()пристрою; чомусь точки в pngапараті набагато швидші, ніж у X11пристрої, але прискорення швидкості X11порівнянні ( X11(type="cairo")було повільніше, ніж X11(type="Xlib")у моїх експериментах).

"bigplotfix.R" тестовий вихід

Я написав це через те, що мені набридло plot()випадково працювати на великому наборі даних (наприклад, файл WAV). У таких випадках мені доведеться вибирати між очікуванням декількох хвилин, щоб завершити змову, і закінчувати свій R сеанс сигналом (тим самим втрачаючи мою недавню історію команд та змінних). Тепер, якщо я можу пам’ятати, щоб завантажити цей файл перед кожним сеансом, я можу насправді отримати корисний сюжет у цих випадках. Невелике попереджувальне повідомлення вказує, коли дані сюжету були "стиснуті".

# 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

Можливо, я буду ухилятися від свого методу, погані спогади про одного з моїх дослідницьких профі, що кричали на людей за те, що вони викидали хороші дані, перекладаючи їх у категорії (звичайно, я згоден зараз на дні, хале), не знаю. У будь-якому випадку, якщо ви говорите про розсіювач, то у мене були ті самі проблеми. Тепер, коли я маю числові дані, для мене немає особливого сенсу класифікувати їх для аналізу. Але візуалізація - це інша історія. Що я виявив, що найкраще працює для мене, це спочатку (1) розбити вашу незалежну змінну на групи за допомогою функції cut. Ви можете пограти з кількістю груп, а потім (2) просто побудуйте DV проти скороченої версії IV. R генерує коробкові сюжети замість огидного сюжетного розсіювання. Я рекомендую видалити залишки з графіку (використовуйте параметр outline = FALSE в команді plot). Знову ж таки, я НІКОЛИ б не витрачав ідеально хороші числові дані, класифікуючи та аналізуючи. Занадто багато питань для цього. Хоча я знаю, що це делікатний предмет дискусій. Але робити це спеціально для того, щоб принаймні зробити деякий візуальний сенс із даних, я не отримав великої шкоди від цього. Я побудував дані, розміром яких 10 мільйонів, і все-таки вдалося зрозуміти їх із цього методу. Сподіваюся, що це допомагає! З повагою! я бачив з цього. Я побудував дані, розмірами яких є 10М, і все-таки вдалося вияснити їх із цього методу. Сподіваюся, що це допомагає! З повагою! я бачив з цього. Я побудував дані, розміром яких 10 мільйонів, і все-таки вдалося зрозуміти їх із цього методу. Сподіваюся, що це допомагає! З повагою!


0

Протягом великих часових рядів я полюбив smoothScatter (частина бази R не менше). Мені часто доводиться включати деякі додаткові дані, і збереження базового API сюжету дуже корисне, наприклад:

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)

Що дає (якщо ви помилуєте дизайн):

розкидати гладкий приклад

Він завжди доступний і добре працює з величезними наборами даних, тому приємно принаймні поглянути на те, що у вас є.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.