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.