forma pirónica de analizar / dividir URL en un dataframe de pandas

Tengo un df que tiene miles de enlaces como los de abajo, para diferentes usuarios, en una columna con la etiqueta url:

https://www.google.com/something https://mail.google.com/anohtersomething https://calendar.google.com/somethingelse https://www.amazon.com/yetanotherthing 

Tengo el siguiente código:

 import urlparse df['domain'] = '' df['protocol'] = '' df['domain'] = '' df['path'] = '' df['query'] = '' df['fragment'] = '' unique_urls = df.url.unique() l = len(unique_urls) i=0 for url in unique_urls: i+=1 print "\r%d / %d" %(i, l), split = urlparse.urlsplit(url) row_index = df.url == url df.loc[row_index, 'protocol'] = split.scheme df.loc[row_index, 'domain'] = split.netloc df.loc[row_index, 'path'] = split.path df.loc[row_index, 'query'] = split.query df.loc[row_index, 'fragment'] = split.fragment 

El código es capaz de analizar y dividir las URL correctamente, pero es lento, ya que estoy iterando sobre cada fila de la df. ¿Hay una manera más eficiente de analizar las URL?

Puedes usar Series.map para lograr lo mismo en una línea:

 df['protocol'],df['domain'],df['path'],df['query'],df['fragment'] = zip(*df['url'].map(urlparse.urlsplit)) 

Usando timeit, esto se ejecutó en 2.31 ms por bucle en lugar de 179 ms por bucle como en el método original, cuando se ejecuta en 186 urls. (Sin embargo, tenga en cuenta que el código no está optimizado para duplicados y ejecutará las mismas URL a través de múltiples tiempos).

Código Completo:

 import pandas urls = ['https://www.google.com/something','https://mail.google.com/anohtersomething','https://www.amazon.com/yetanotherthing'] # tested with list of 186 urls instead df['protocol'],df['domain'],df['path'],df['query'],df['fragment'] = zip(*df['url'].map(urlparse.urlsplit)) 

Creo que están ocurriendo demasiadas búsquedas cuando escribes de nuevo al df . Parece que cada df.loc[row_index, ...] necesita verificar tantas filas como df.url URL en total (tamaño de df.url ). Significa que primero miras todas las filas al menos una vez para encontrar las URL únicas, luego para cada url lo haces nuevamente para encontrar filas coincidentes, y luego nuevamente para cada escritura. Por lo tanto, asumiendo que solo toma una exploración completa, está escaneando la tabla en promedio 1+N+(5N/2) veces. Solo deberías necesitar una vez de verdad.

A menos que tenga una gran cantidad de repeticiones, podría ignorar los duplicados, atravesar df fila por fila y asegurarse de que está utilizando el índice de enteros para cada iteración. ( .iloc ) Si no está almacenando otros datos en la fila, también puede asignar todos los campos a la vez:

 df.iloc[idx] = {'protocol': ..., 'domain': ..., ...}