38 votes

Tracer efficacement des centaines de millions de points dans R

Est plot() la manière la plus efficace de tracer 100 millions de points de données environ dans R ? J'aimerais en tracer quelques-uns. Attracteurs de Clifford . Voici un exemple d'une image que j'ai réduite à partir d'une très grande image :

A Clifford attractor

Aquí Voici un lien vers un code que j'ai utilisé pour tracer une très grande image 8K (7680x4320).

Il ne faut pas longtemps pour générer 50 ou 100 millions de points (à l'aide de Rcpp), ni pour obtenir la valeur hexadécimale de la couleur + la transparence, mais le tracé proprement dit et la sauvegarde sur le disque sont extrêmement lent.

  • Existe-t-il un moyen plus rapide de tracer (et de sauvegarder) tous ces points ?
  • R est-il simplement un mauvais outil pour ce travail ?
  • Quels outils utiliseriez-vous pour tracer les points des milliards, même si vous ne pouviez pas tous les faire rentrer dans le bélier ?
  • Comment aurait-on fait un tracé de très haute résolution de ce type (couleur + transparence) avec les logiciels et le matériel des années 1990 ?

Edit : code utilisé

# Load packages
library(Rcpp)
library(viridis)

# output parameters
output_width = 1920 * 4
output_height = 1080 * 4
N_points = 50e6
point_alpha = 0.05 #point transperancy

# Attractor parameters
params <- c(1.886,-2.357,-0.328, 0.918)

# C++ function to rapidly generate points
cliff_rcpp <- cppFunction(
    "
    NumericMatrix cliff(int nIter, double A, double B, double C, double D) {
    NumericMatrix x(nIter, 2);
    for (int i=1; i < nIter; ++i) {
    x(i,0) = sin(A*x(i-1,1)) + C*cos(A*x(i-1,0));
    x(i,1) = sin(B*x(i-1,0)) + D*cos(B*x(i-1,1));
    }
    return x;
    }"
)

# Function for mapping a point to a colour
map2color <- function(x, pal, limits = NULL) {
    if (is.null(limits))
        limits = range(x)
    pal[findInterval(x,
                     seq(limits[1], limits[2], length.out = length(pal) + 1),
                     all.inside = TRUE)]
}

# Obtain matrix of points
cliff_points <- cliff_rcpp(N_points, params[1], params[2], params[3], params[4])

# Calculate angle between successive points
cliff_angle <- atan2(
    (cliff_points[, 1] - c(cliff_points[-1, 1], 0)),
    (cliff_points[, 2] - c(cliff_points[-1, 2], 0))
)

# Obtain colours for points
available_cols <-
    viridis(
        1024,
        alpha = point_alpha,
        begin = 0,
        end = 1,
        direction = 1
    )

cliff_cols <- map2color(
    cliff_angle,
    c(available_cols, rev(available_cols))
)

# Output image directly to disk
jpeg(
    "clifford_attractor.jpg",
    width = output_width,
    height = output_height,
    pointsize = 1,
    bg = "black",
    quality = 100

)
    plot(
        cliff_points[-1, ],
        bg = "black",
        pch = ".",
        col = cliff_cols
    )

dev.off()

0 votes

Peut-être utiliser image au lieu de plot ?

0 votes

@KarstenW. J'y ai pensé, mais il faudrait que je fasse moi-même le mappage des millions de points sur un emplacement de pixel et que je détermine la couleur correcte lorsque 2 points ou plus se retrouvent sur le même pixel. C'est quelque chose que je ne sais pas faire efficacement, mais je pourrais probablement jouer avec.

1 votes

Juste par curiosité, comment la vitesse du png() comparer avec celle de jpeg() ?

5voto

dcl Points 352

J'ai récemment découvert le Scattermore pour R, qui est environ un ordre de grandeur plus rapide que la fonction de tracé standard de R. scattermoreplot() prend ~2 minutes pour tracer 100m points avec couleur et transparence, alors que plot() prend environ une demi-heure.

2voto

Florian Points 1866

Je suis actuellement en train d'explorer datashader ( http://www.datashader.org ). Si vous êtes prêt à travailler avec python, cela pourrait être une solution élégante au problème.

1 votes

Voici un explorateur d'attracteurs complet utilisant datashader : anaconda.org/jbednar/datashaderattractors/notebook vous pouvez régler la résolution comme vous le souhaitez. Il pourrait être rendu beaucoup plus efficace en le traçant par lots (générer un lot, tracer un lot, répéter), mais pour l'instant, il privilégie la simplicité.

0voto

Sara Points 72

Peut-être que geom_hex() du paquet ggplo2 peut être une solution ? https://ggplot2.tidyverse.org/reference/geom_hex.html

1 votes

Bonjour @Sara, cela ne produirait pas l'effet escompté. Je veux préserver autant de détails que possible, et non bin les pixels.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X