studio read data csv2 r memory-management file-io

data - read table r studio



Leyendo un archivo csv de 40 GB en R usando bigmemory (2)

El título es bastante explicativo aquí, pero lo explicaré de la siguiente manera. Algunas de mis técnicas actuales para atacar este problema se basan en las soluciones presentadas en this pregunta. Sin embargo, me enfrento a varios desafíos y limitaciones, por lo que me preguntaba si alguien podría intentar hacer una prueba de este problema. Estoy tratando de resolver el problema utilizando el paquete bigmemory , pero he tenido dificultades.

Restricciones actuales:

  • Usando un servidor linux con 16 GB de RAM
  • Tamaño de 40 GB CSV
  • Nº de filas: 67,194,126,114.

Desafíos

  • Debe poder muestrear aleatoriamente conjuntos de datos más pequeños (5-10 millones de filas) de una estructura de datos big.matrix o equivalente.
  • Debe poder eliminar cualquier fila con una sola instancia de NULL mientras se analiza en una estructura de datos big.matrix o equivalente.

Hasta ahora, los resultados no son buenos. Evidentemente, estoy fallando en algo o tal vez, simplemente no entiendo lo suficientemente bien la documentación de bigmemory . Entonces, pensé que pediría aquí para ver si alguien ha usado

¿Algún consejo, consejo sobre esta línea de ataque, etc.? ¿O debería cambiarme a otra cosa? Pido disculpas si esta pregunta es muy similar a la anterior, pero pensé que la escala de datos era aproximadamente 20 veces más grande que las preguntas anteriores. Gracias !


Esta es una solución R pura al desafío de muestrear desde un archivo de texto grande; tiene el mérito adicional de dibujar una muestra aleatoria de exactamente n. No es demasiado ineficiente, aunque las líneas se analizan en vectores de caracteres y esto es relativamente lento.

Comenzamos con una firma de función, donde proporcionamos un nombre de archivo, el tamaño de la muestra que queremos dibujar, una semilla para el generador de números aleatorios (¡para que podamos reproducir nuestra muestra aleatoria!), Una indicación de si hay un encabezado línea, y luego una función de "lector" que usaremos para analizar la muestra en el objeto visto por R, incluyendo argumentos adicionales ... que la función de lector podría necesitar

fsample <- function(fname, n, seed, header=FALSE, ..., reader=read.csv) {

La función siembra el generador de números aleatorios, abre una conexión y lee en la línea de encabezado (opcional)

set.seed(seed) con <- file(fname, open="r") hdr <- if (header) { readLines(con, 1L) } else character()

El siguiente paso es leer un trozo de n líneas, inicializando un contador del número total de líneas vistas

buf <- readLines(con, n) n_tot <- length(buf)

Continúe leyendo fragmentos de n líneas, deteniéndose cuando no haya más información.

repeat { txt <- readLines(con, n) if ((n_txt <- length(txt)) == 0L) break

Para cada fragmento, dibuje una muestra de n_keep lines, con el número de líneas proporcionales a la fracción del total de líneas en el fragmento actual. Esto asegura que las líneas se muestrean uniformemente sobre el archivo. Si no hay líneas que mantener, pase al siguiente fragmento.

n_tot <- n_tot + n_txt n_keep <- rbinom(1, n_txt, n_txt / n_tot) if (n_keep == 0L) next

Elija las líneas a mantener y las líneas a reemplazar, y actualice el búfer

keep <- sample(n_txt, n_keep) drop <- sample(n, n_keep) buf[drop] <- txt[keep] }

Cuando se realiza la entrada de datos, analizamos el resultado utilizando el lector y devolvemos el resultado

reader(textConnection(c(hdr, buf), header=header, ...) }

La solución podría hacerse más eficiente, pero un poco más complicada, utilizando readBin y buscando saltos de línea como lo sugiere Simon Urbanek en la lista de correo de R-devel. Aquí está la solución completa

fsample <- function(fname, n, seed, header=FALSE, ..., reader = read.csv) { set.seed(seed) con <- file(fname, open="r") hdr <- if (header) { readLines(con, 1L) } else character() buf <- readLines(con, n) n_tot <- length(buf) repeat { txt <- readLines(con, n) if ((n_txt <- length(txt)) == 0L) break n_tot <- n_tot + n_txt n_keep <- rbinom(1, n_txt, n_txt / n_tot) if (n_keep == 0L) next keep <- sample(n_txt, n_keep) drop <- sample(n, n_keep) buf[drop] <- txt[keep] } reader(textConnection(c(hdr, buf)), header=header, ...) }


No sé sobre bigmemory , pero para satisfacer sus desafíos no necesita leer el archivo. Simplemente canalice un poco de bash / awk / sed / python / cualquier proceso para realizar los pasos que desee, es decir, NULL líneas NULL y selecciona aleatoriamente N líneas, y luego lee eso en.

Aquí hay un ejemplo que usa awk (asumiendo que quiere 100 líneas aleatorias de un archivo que tiene 1M líneas).

read.csv(pipe(''awk -F, /'BEGIN{srand(); m = 100; length = 1000000;} !/NULL/{if (rand() < m/(length - NR + 1)) { print; m--; if (m == 0) exit; }}/' filename'' )) -> df

No era obvio lo que quería decir con NULL , por lo que utilicé una comprensión literal de él, pero debería ser fácil modificarlo para que se ajuste a sus necesidades.