Cálculo de la distancia y el tiempo entre los puntos de referencia para archivos grandes -- python campo con performance campo con python-3.x campo con numpy campo con pandas camp codereview Relacionados El problema

Calculating distance and time between waypoints for large files


8
vote

problema

Español

Esto es muy similar a otro código que he publicado, sin embargo, esto está diseñado para archivos CSV muy grandes, por ejemplo, 35 GB.

Los archivos generalmente se ven así:

  9e77d54918dd25c3f9d2e5354ec86666,0,2015-10-01T14:14:15.000Z,45.0988,7.5811,, 9e77d54918dd25c3f9d2e5354ec86666,1,2015-10-01T14:17:15.000Z,45.0967,7.5793,, 9e77d54918dd25c3f9d2e5354ec86666,2,2015-10-01T14:20:15.000Z,45.1012,7.6144,, 9e77d54918dd25c3f9d2e5354ec86666,3,2015-10-01T14:23:15.000Z,45.0883,7.6479,, 9e77d54918dd25c3f9d2e5354ec86666,4,2015-10-01T14:26:15.000Z,45.0774,7.6444,, 9e77d5jhg35hg345hghge5354ec84751,0,2015-10-04T22:36:32.000Z,48.0723,7.6442,, ect...   

El código que he escrito funciona con la suma de la distancia entre cada uno de los puntos de ruta, así como el tiempo necesario y el número total de puntos de referencia. Aquí está en su totalidad:

  import pandas as pd import numpy as np   EarthRadius = 6371 #km  def distance(group): #calculate distances using Equirectangular approximation     lat = np.radians(group.Lat)     lon = np.radians(group.Lon)     endLon = lon.shift(-1)     endLat = lat.shift(-1)     x = (endLon - lon) * np.cos(0.5 * (endLat + lat))     y = endLat - lat     D = EarthRadius * np.sqrt(x**2 + y**2)     return D.sum()  def timedelt(group):  #calculate length of trip     a = np.around((pd.to_datetime(group['Date']).max() - pd.to_datetime(group['Date']).min()).seconds/60, decimals=2)     return a  def tripStatistics(trip):#Helper function to output distance and number of waypoints     return pd.Series({"TripID":chunk.iloc[0,0],"Distance": distance(trip),"No. of Waypoints": len(trip),"Time Taken(Mins)": timedelt(trip)})   def iterateIDs(file): #create chunks based on tripID     csv_reader = pd.read_csv(file, iterator=True, chunksize=1, header=None, usecols=[0, 2, 3, 4],names=['TripID', 'Date', 'Lat', 'Lon'])     first_chunk = csv_reader.get_chunk()     id = first_chunk.iloc[0,0]     chunk = pd.DataFrame(first_chunk)     for l in csv_reader:         if id == l.iloc[0,0]:             id = l.iloc[0,0]             chunk = chunk.append(l)             continue         id = l.iloc[0,0]         yield chunk         chunk = pd.DataFrame(l)     yield chunk  output = pd.DataFrame(columns=['TripID','Distance','No. of Waypoints','Time Taken(Mins)']) chunkIterate = iterateIDs("TripRecordsReportWaypoints.csv")  for chunk in chunkIterate:     temp = tripStatistics(chunk)     output = output.append(temp, ignore_index=True)   output['Waypoint Frequency(Secs)'] = np.around(60*output['Time Taken(Mins)']/output['No. of Waypoints'], decimals=2) output.reset_index().to_csv('TripDetails.csv', sep=',', index=False)   

Me pregunto si hay algo en mi código que podría ralentizar las velocidades de procesamiento. Lo puse ejecutando en el archivo de 35 GB mencionado anteriormente y ha estado yendo por más de 24 horas ahora. Es la primera vez que he usado generadores, así que espero que no haya hecho un error simple.

Como un poco de comparación, había escrito una pieza de código anterior similar, pero sin dividir el archivo CSV en trozos con la función 9988777665544332 generador. Procesó un archivo de 200 MB en 100 segundos. Una extrapolación lineal de eso significaría que solo tomaría 3 horas procesar un archivo de 35 GB.

Original en ingles

This is very similar to other code I've posted, however this is designed for very large CSV files, for example 35GB.

The files typically look like this:

9e77d54918dd25c3f9d2e5354ec86666,0,2015-10-01T14:14:15.000Z,45.0988,7.5811,, 9e77d54918dd25c3f9d2e5354ec86666,1,2015-10-01T14:17:15.000Z,45.0967,7.5793,, 9e77d54918dd25c3f9d2e5354ec86666,2,2015-10-01T14:20:15.000Z,45.1012,7.6144,, 9e77d54918dd25c3f9d2e5354ec86666,3,2015-10-01T14:23:15.000Z,45.0883,7.6479,, 9e77d54918dd25c3f9d2e5354ec86666,4,2015-10-01T14:26:15.000Z,45.0774,7.6444,, 9e77d5jhg35hg345hghge5354ec84751,0,2015-10-04T22:36:32.000Z,48.0723,7.6442,, ect... 

The code I've written works out the sum of the distance between each of the waypoints, as well as the time taken and total number of waypoints. Here it is in entirety:

import pandas as pd import numpy as np   EarthRadius = 6371 #km  def distance(group): #calculate distances using Equirectangular approximation     lat = np.radians(group.Lat)     lon = np.radians(group.Lon)     endLon = lon.shift(-1)     endLat = lat.shift(-1)     x = (endLon - lon) * np.cos(0.5 * (endLat + lat))     y = endLat - lat     D = EarthRadius * np.sqrt(x**2 + y**2)     return D.sum()  def timedelt(group):  #calculate length of trip     a = np.around((pd.to_datetime(group['Date']).max() - pd.to_datetime(group['Date']).min()).seconds/60, decimals=2)     return a  def tripStatistics(trip):#Helper function to output distance and number of waypoints     return pd.Series({"TripID":chunk.iloc[0,0],"Distance": distance(trip),"No. of Waypoints": len(trip),"Time Taken(Mins)": timedelt(trip)})   def iterateIDs(file): #create chunks based on tripID     csv_reader = pd.read_csv(file, iterator=True, chunksize=1, header=None, usecols=[0, 2, 3, 4],names=['TripID', 'Date', 'Lat', 'Lon'])     first_chunk = csv_reader.get_chunk()     id = first_chunk.iloc[0,0]     chunk = pd.DataFrame(first_chunk)     for l in csv_reader:         if id == l.iloc[0,0]:             id = l.iloc[0,0]             chunk = chunk.append(l)             continue         id = l.iloc[0,0]         yield chunk         chunk = pd.DataFrame(l)     yield chunk  output = pd.DataFrame(columns=['TripID','Distance','No. of Waypoints','Time Taken(Mins)']) chunkIterate = iterateIDs("TripRecordsReportWaypoints.csv")  for chunk in chunkIterate:     temp = tripStatistics(chunk)     output = output.append(temp, ignore_index=True)   output['Waypoint Frequency(Secs)'] = np.around(60*output['Time Taken(Mins)']/output['No. of Waypoints'], decimals=2) output.reset_index().to_csv('TripDetails.csv', sep=',', index=False) 

I'm wondering if there is anything in my code that might slow down processing speeds. I set it running on the previously mentioned 35GB file and it's been going for over 24 hours now. It's the first time I've used generators so I hope I've not made some simple error.

As a bit of a comparison, I had written a previous piece of code that is similar but without splitting the CSV file into chunks with the iterateIDs generator function. It processed a 200MB file in 100 seconds. A linear extrapolation of that would mean it would take only 3 hours to process a 35GB file.

              
     
     

Lista de respuestas

1
 
vote

Esta línea parece problemas:

          chunk = chunk.append(l)   

la Docs Di que lo hará "Añadir filas de otro hasta el final de este marco, devolviendo un nuevo objeto". Si el nuevo objeto debía ser pequeño, conteniendo una referencia al objeto anterior, entonces ganaría, pero aquí creo que estamos viendo cuadrático de copia de comportamiento. Considere usar .conCAT () en su lugar, con Copy = False. O tal vez puedas preetrocar. Verifique que las columnas de l siempre coincidan con los del 9988776655544333 .

Recomiendo agregar informes periódicos de progreso que mencionen el rendimiento y el tamaño del trozo, para ver dónde se cae el rendimiento de un acantilado. Haga una ejecución de tiempo con la llamada a la salida. Append comentó. Verificar que los tamaños de grupo esperados se transmiten en distance() también serían útiles. Y definitivamente use cprofile, como sugiere graipher.

 

This line looks like trouble:

        chunk = chunk.append(l) 

The docs say it will "append rows of other to the end of this frame, returning a new object." If the new object were to be small, containing a reference to the old object, then you would win, but here I think we're looking at quadratic copying behavior. Consider using .concat() instead, with copy=False. Or perhaps you can preallocate. Verify that the columns of l always match those of the existing chunk.

I recommend adding periodic progress reports that mention throughput and chunk size, to see where performance falls off a cliff. Do a timing run with the call to output.append commented out. Verifying that expected group sizes are passed into distance() would be helpful, too. And definitely use cProfile, as Graipher suggests.

 
 

Relacionados problema

7  Salida de parcelas de dispersión [cerrada]  ( Outputting scatter plots ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

2  K_nearest_neighbors desde cero [cerrado]  ( K nearest neighbors from scratch ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

5  Automatizar un conjunto A de informes semanales, incluidos los gráficos y la entrega de informes  ( Automating a set a of weekly reports including graphs and delivery of reports ) 
He estado escribiendo código para automatizar algunos informes semanales. Tuve Ayuda sobre el desbordamiento de la pila . Tengo código que funciona en su may...

8  Python CSV a XML Converter  ( Python csv to xml converter ) 
Estoy creando una aplicación que se lee en los datos de un archivo CSV y crea un archivo XML usando LXML. El siguiente código funciona como se esperaba. Sin e...

4  Cuentos acumulativos de artículos en un marco de datos Panda  ( Cumulative counts of items in a pandas dataframe ) 
Estoy usando un conteo de datos lleno de encabezados / nombres de campo para desarrollar un esquema y necesito valores únicos para cada encabezado, pero cada ...

10  Tkinter GUI por hacer ediciones muy simples a Pandas DataFrames  ( Tkinter gui for making very simple edits to pandas dataframes ) 
Es parte de una aplicación separada que permite a los usuarios interactuar muy libremente con diferentes bases de datos y verificar los posibles errores y rea...

2  Regresión en Pandas DataFrame  ( Regression on pandas dataframe ) 
Estoy trabajando en la siguiente tarea y estoy un poco perdido: construir un modelo de regresión que predecirá la puntuación de calificación de cada Prod...

0  Manipulando los cuadros de datos en Pandas  ( Manipulating dataframes on pandas ) 
Recientemente no pudo finalizar un código para una entrevista de trabajo. Uno de los problemas es que decidí usar Pandas (tenía sentido), pero no estaba famil...

7  La forma más rápida de escribir un archivo CSV grande en Python  ( Fastest way to write large csv file in python ) 
Soy bastante nuevo para Python y Pandas, pero tratando de mejorar con él para analizar y procesar archivos de datos grandes. Actualmente estoy trabajando en u...

6  Valores coincidentes de la tabla HTML para actualizar los valores en Pandas DataFrame  ( Matching values from html table for updating values in pandas dataframe ) 
Esto es más un ejercicio para que me utilice a Pandas y sus cuadros de datos. Para aquellos que no escucharon de él: Panda es un paquete de Python que prop...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos