Ejecuté el siguiente código en RStudio:
exo <- read.csv('exoplanets.csv',TRUE,",") df <- data.frame(exo) ranks <- 570 files <- 3198 datas <- vector() for ( w in 2:files ) { listas <-vector() for ( i in 1:ranks) { name <- as.character(df[i,w]) listas <- append (listas, name) } datas <- append (datas, listas) }
Lee un enorme archivo CSV de la NASA, lo convierte en un marco de datos, convierte cada elemento en una cadena y los agrega a un vector.
RStudio tomó 4 min y 15 segundos.
Así que decidí implementar el mismo código en Julia. Ejecuté lo siguiente en VS Code:
using CSV, DataFrames df = CSV.read("exoplanets.csv", DataFrame) fil, col = 570, 3198 arr = [] for i in 2:fil for j in 1:col push!(arr, string(df[i, j])) end end
El resultado fue bueno. ¡El código de Julia tomó solo 1 minuto y 25 segundos!
Luego, por pura curiosidad, implementé el mismo código esta vez en Python para comparar. Ejecuté lo siguiente en VS Code:
import numpy as np import pandas as pd exo = pd.read_csv("exoplanets.csv") arr = np.array(exo) fil, col = 570, 3198 lis = [] for i in range(1, fil): for j in range(col): lis.append(arr[i][j].astype('str'))
¡El resultado me impactó! ¡¡¡Solo 35 segundos!!! Y en Spyder de Anaconda solo 26 segundos!!! ¡¡¡Casi 2 millones de carrozas!!! ¿Julia es más lenta que Python en el análisis de datos? ¿Puedo mejorar el código de Julia?
Depende de lo que quiera probar (es decir, si quiere probar el bucle o simplemente desea obtener un resultado rápido). Supongo que quieres el resultado rápido y en un código limpio, en cuyo caso escribiría esta operación de la siguiente manera en Julia:
arr = reduce(vcat, eachrow(Matrix(string.(df[2:570, 1:3198]))))
¿Puede confirmar que esto produce el resultado esperado y cuál es el momento de esta operación? (en esto, supongo que tiene más filas que 570 y más columnas que 3198, así que las subconjunto primero)
Si desea probar los bucles, los comentarios debajo de su respuesta comenzarían a ser relevantes.
También tenga en cuenta que su código para DataFrames.jl no realiza la misma operación que los códigos en R y Python (el orden de bucle es diferente, por lo que podría verificar dos veces lo que necesita). Esta diferencia es crucial para el rendimiento. Le he dado el código que reproduce el comportamiento de su código DataFrames.jl (que es una variante más difícil/lenta de lo que quiere hacer en comparación con los códigos R/Python)
NOTA: Escribí lo siguiente asumiendo que desea el otro orden de columnas (como en los ejemplos de Python y R). Es más eficiente en Julia de esta manera; para que funcione de manera equivalente a su comportamiento original, permute la lógica o sus datos en los lugares correctos (a la izquierda como ejercicio). La respuesta de Bogumił ya hace lo correcto.
Coloque cosas en funciones, asigne previamente donde sea posible, itere en orden, use vistas y use funciones integradas y transmisión:
function tostringvector(d) r, c = size(d) result = Vector{String}(undef, r*c) v = reshape(result, r, c) for (rcol, dcol) in zip(eachcol(v), eachcol(d)) @inbounds rcol .= string.(dcol) end return result end
Que ciertamente se puede optimizar más.
O más corto, haciendo uso de lo que ya proporciona DataFrames
:
tostringvector(d) = vec(Matrix(string.(d)))
Dado su comentario a la respuesta de @phipsgabler, lo que está cronometrando aquí son los costos fijos de importar los módulos y compilar más que la tarea en sí.