Pandas: Falta valor imputación -- python campo con performance campo con pandas camp codereview Relacionados El problema

Pandas: missing value imputation


2
vote

problema

Español

Quiero encontrar una solución más eficiente para el siguiente problema:

Mi conjunto de datos es sobre juegos en línea. Cada jugador puede tener múltiples reproducciones (filas en el DF). Cada juego tiene su marca de tiempo correspondiente. Sin embargo, algunos eventos carecen de su identificación (identificador de sesión). Necesito un método eficiente para llenar la NAN de las columnas de ID, usando información de las otras dos columnas.

Este es el conjunto de datos:

  d = {'player': ['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '4'],         'date': ['2018-01-01 00:17:01', '2018-01-01 00:17:05','2018-01-01 00:19:05', '2018-01-01 00:21:07', '2018-01-01 00:22:09',                   '2018-01-01 00:22:17', '2018-01-01 00:25:09', '2018-01-01 00:25:11', '2018-01-01 00:27:28', '2018-01-01 00:29:29',                   '2018-01-01 00:30:35',  '2018-02-01 00:31:16', '2018-02-01 00:35:22', '2018-02-01 00:38:16',                   '2018-02-01 00:38:20', '2018-02-01 00:55:15', '2018-01-03 00:55:22', '2018-01-03 00:58:16',                   '2018-01-03 00:58:21', '2018-03-01 01:00:35', '2018-03-01 01:20:16', '2018-03-01 01:31:16', '2018-03-01 02:44:21'],          'id': [np.nan, np.nan, 'a', 'a', 'b', np.nan, 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'e', 'e', np.nan, 'f', 'f',                 'g', np.nan, 'f', 'g', 'h']}  #create dataframe df = pd.DataFrame(data=d) df    player      date          id 0   1   2018-01-01 00:17:01 NaN 1   1   2018-01-01 00:17:05 NaN 2   1   2018-01-01 00:19:05 a 3   1   2018-01-01 00:21:07 a 4   1   2018-01-01 00:22:09 b 5   1   2018-01-01 00:22:17 NaN 6   1   2018-01-01 00:25:09 b 7   1   2018-01-01 00:25:11 c 8   1   2018-01-01 00:27:28 c 9   1   2018-01-01 00:29:29 c 10  1   2018-01-01 00:30:35 c 11  2   2018-02-01 00:31:16 d 12  2   2018-02-01 00:35:22 d 13  2   2018-02-01 00:38:16 e 14  2   2018-02-01 00:38:20 e 15  2   2018-02-01 00:55:15 NaN 16  3   2018-01-03 00:55:22 f 17  3   2018-01-03 00:58:16 f 18  3   2018-01-03 00:58:21 g 19  3   2018-03-01 01:00:35 NaN 20  3   2018-03-01 01:20:16 f 21  3   2018-03-01 01:31:16 g 22  4   2018-03-01 02:44:21 h   

Esta fue mi línea de razonamiento:

1. Jugador y ID de grupo

Computando la primera y última fecha para cada juego.

  my_agg = df.groupby(['player', 'id']).date.agg([min, max]) my_agg                         min           max  player id           1    a  2018-01-01 00:19:05  2018-01-01 00:21:07          b  2018-01-01 00:22:09  2018-01-01 00:25:09          c  2018-01-01 00:25:11  2018-01-01 00:30:35     2    d  2018-02-01 00:31:16  2018-02-01 00:35:22          e  2018-02-01 00:38:16  2018-02-01 00:38:20     3    f  2018-01-03 00:55:22  2018-03-01 01:20:16          g  2018-01-03 00:58:21  2018-03-01 01:31:16     4    h  2018-03-01 02:44:21  2018-03-01 02:44:21   

2. Crear una función

Eso compara la marca de tiempo de la reproducción a cada ID disponible y vea si se cae o no dentro del rango. Básicamente, si cae dentro del rango de una sola sesión de ID de juego, quiero llenar el NAN con la etiqueta de identificación. Si no está dentro del rango de ningún ID de sesión, quiero llenar el NAN con 0. Si está dentro del rango de múltiples sesiones (teóricamente, no debe ser), llena el valor faltante con -99.

  #define a function to sort the missing values  def check_function(time):     #compare every date event with the range of the sessions.      current_sessions = group.loc[(group['min']<time) & (group['max']>time)]     #store length, that is the number of matches.      count = len(current_sessions)     #How many matches are there for any missing id value?     # if 0 the event lies outside all the possible ranges     if count == 0:         return 0     #if >1, it is impossible to say to which session the event belongs     if count > 1:         return -99     #in this case the event belongs clearly to just one session     return current_sessions.index[0][1]   

3. Aplique el reproductor de la función por jugador

y almacene los resultados para crear un nuevo contorno de datos, con la salida deseada.

  grouped = my_agg.groupby(level=0)  final = pd.DataFrame() for name, group in grouped:     mv_per_player = df.loc[df['player'] == name]         mv_per_player.loc[mv_per_player.id.isnull(),'id'] = mv_per_player.loc[mv_per_player.id.isnull(),'date'].apply(check_function)     final = final.append(mv_per_player)  final    player         date       id 0   1   2018-01-01 00:17:01 0 1   1   2018-01-01 00:17:05 0 2   1   2018-01-01 00:19:05 a 3   1   2018-01-01 00:21:07 a 4   1   2018-01-01 00:22:09 b 5   1   2018-01-01 00:22:17 b 6   1   2018-01-01 00:25:09 b 7   1   2018-01-01 00:25:11 c 8   1   2018-01-01 00:27:28 c 9   1   2018-01-01 00:29:29 c 10  1   2018-01-01 00:30:35 c 11  2   2018-02-01 00:31:16 d 12  2   2018-02-01 00:35:22 d 13  2   2018-02-01 00:38:16 e 14  2   2018-02-01 00:38:20 e 15  2   2018-02-01 00:55:15 0 16  3   2018-01-03 00:55:22 f 17  3   2018-01-03 00:58:16 f 18  3   2018-01-03 00:58:21 g 19  3   2018-03-01 01:00:35 -99 20  3   2018-03-01 01:20:16 f 21  3   2018-03-01 01:31:16 g 22  4   2018-03-01 02:44:21 h   

Conclusión

Este proceso funciona, pero ¿hay una manera de hacer que el proceso sea más eficiente y más rápido? Creo que el cuello de botella es el bucle para el bucle, pero no puedo encontrar una solución alternativa.

Original en ingles

I want to find a more efficient solution to the following problem:

My dataset is about online games. Each player may have multiple plays (rows in the df). Each play has its corresponding timestamp. However, some events are lacking their id (session identifier). I need an efficient method to fill the NaN of the id columns, using information from the other two columns.

This is the dataset:

d = {'player': ['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '4'],         'date': ['2018-01-01 00:17:01', '2018-01-01 00:17:05','2018-01-01 00:19:05', '2018-01-01 00:21:07', '2018-01-01 00:22:09',                   '2018-01-01 00:22:17', '2018-01-01 00:25:09', '2018-01-01 00:25:11', '2018-01-01 00:27:28', '2018-01-01 00:29:29',                   '2018-01-01 00:30:35',  '2018-02-01 00:31:16', '2018-02-01 00:35:22', '2018-02-01 00:38:16',                   '2018-02-01 00:38:20', '2018-02-01 00:55:15', '2018-01-03 00:55:22', '2018-01-03 00:58:16',                   '2018-01-03 00:58:21', '2018-03-01 01:00:35', '2018-03-01 01:20:16', '2018-03-01 01:31:16', '2018-03-01 02:44:21'],          'id': [np.nan, np.nan, 'a', 'a', 'b', np.nan, 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'e', 'e', np.nan, 'f', 'f',                 'g', np.nan, 'f', 'g', 'h']}  #create dataframe df = pd.DataFrame(data=d) df    player      date          id 0   1   2018-01-01 00:17:01 NaN 1   1   2018-01-01 00:17:05 NaN 2   1   2018-01-01 00:19:05 a 3   1   2018-01-01 00:21:07 a 4   1   2018-01-01 00:22:09 b 5   1   2018-01-01 00:22:17 NaN 6   1   2018-01-01 00:25:09 b 7   1   2018-01-01 00:25:11 c 8   1   2018-01-01 00:27:28 c 9   1   2018-01-01 00:29:29 c 10  1   2018-01-01 00:30:35 c 11  2   2018-02-01 00:31:16 d 12  2   2018-02-01 00:35:22 d 13  2   2018-02-01 00:38:16 e 14  2   2018-02-01 00:38:20 e 15  2   2018-02-01 00:55:15 NaN 16  3   2018-01-03 00:55:22 f 17  3   2018-01-03 00:58:16 f 18  3   2018-01-03 00:58:21 g 19  3   2018-03-01 01:00:35 NaN 20  3   2018-03-01 01:20:16 f 21  3   2018-03-01 01:31:16 g 22  4   2018-03-01 02:44:21 h 

This was my line of reasoning:

1. Groupby player and id

computing the first and last date for each play.

my_agg = df.groupby(['player', 'id']).date.agg([min, max]) my_agg                         min           max  player id           1    a  2018-01-01 00:19:05  2018-01-01 00:21:07          b  2018-01-01 00:22:09  2018-01-01 00:25:09          c  2018-01-01 00:25:11  2018-01-01 00:30:35     2    d  2018-02-01 00:31:16  2018-02-01 00:35:22          e  2018-02-01 00:38:16  2018-02-01 00:38:20     3    f  2018-01-03 00:55:22  2018-03-01 01:20:16          g  2018-01-03 00:58:21  2018-03-01 01:31:16     4    h  2018-03-01 02:44:21  2018-03-01 02:44:21 

2. Create a function

that compares the timestamp of the play to every id available, and see whether or not it falls within range. Basically, if it falls within range of a single session of play id, I want to fill the NaN with the id label. If it is not within range of any session id, I want to fill the NaN with 0. If it is within range of multiple sessions (theoretically it should not be), it fills the missing value with -99.

#define a function to sort the missing values  def check_function(time):     #compare every date event with the range of the sessions.      current_sessions = group.loc[(group['min']<time) & (group['max']>time)]     #store length, that is the number of matches.      count = len(current_sessions)     #How many matches are there for any missing id value?     # if 0 the event lies outside all the possible ranges     if count == 0:         return 0     #if >1, it is impossible to say to which session the event belongs     if count > 1:         return -99     #in this case the event belongs clearly to just one session     return current_sessions.index[0][1] 

3. Apply the function player by player

And store the results to create a new dataframe, with the desired output.

grouped = my_agg.groupby(level=0)  final = pd.DataFrame() for name, group in grouped:     mv_per_player = df.loc[df['player'] == name]         mv_per_player.loc[mv_per_player.id.isnull(),'id'] = mv_per_player.loc[mv_per_player.id.isnull(),'date'].apply(check_function)     final = final.append(mv_per_player)  final    player         date       id 0   1   2018-01-01 00:17:01 0 1   1   2018-01-01 00:17:05 0 2   1   2018-01-01 00:19:05 a 3   1   2018-01-01 00:21:07 a 4   1   2018-01-01 00:22:09 b 5   1   2018-01-01 00:22:17 b 6   1   2018-01-01 00:25:09 b 7   1   2018-01-01 00:25:11 c 8   1   2018-01-01 00:27:28 c 9   1   2018-01-01 00:29:29 c 10  1   2018-01-01 00:30:35 c 11  2   2018-02-01 00:31:16 d 12  2   2018-02-01 00:35:22 d 13  2   2018-02-01 00:38:16 e 14  2   2018-02-01 00:38:20 e 15  2   2018-02-01 00:55:15 0 16  3   2018-01-03 00:55:22 f 17  3   2018-01-03 00:58:16 f 18  3   2018-01-03 00:58:21 g 19  3   2018-03-01 01:00:35 -99 20  3   2018-03-01 01:20:16 f 21  3   2018-03-01 01:31:16 g 22  4   2018-03-01 02:44:21 h 

Conclusion

This process works, but is there a way to make the process more efficient and faster? I think the bottleneck is the for loop, but I cannot find an alternative solution.

        

Lista de respuestas


Relacionados problema

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

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...

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...

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...

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...

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...

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...

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...

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 ...

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




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