Tengo un conjunto de datos que creé al fusionar 2 df en la columna "NOMBRE" y ahora tengo un conjunto de datos más grande. Para terminar el DF, quiero aplicarle algo de lógica para limpiarlo.
Requisitos: Quiero seleccionar el 'NOMBRE' único, pero quiero hacer coincidir el nombre con la fila de Ventas más alta, y si después de pasar por la columna Ventas, todas las filas son menos de 10, luego muévase a la columna Llamadas y seleccione la fila más alta. fila con la Llamada más alta, y si todas las llamadas en las 'LLAMADAS' son menos de 10, entonces muévase a la Columna de Objetivo y seleccione el Objetivo más alto. No se suman filas.
Aquí está mi DF:
NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 0 OFFICE 1 2222277 84 170 265 1 OFFICE 1 2222278 26 103 287 2 OFFICE 1 2222278 97 167 288 3 OFFICE 2 2222289 7 167 288 4 OFFICE 2 2222289 3 130 295 5 OFFICE 2 2222289 9 195 257 6 OFFICE 3 1111111 1 2 286 7 OFFICE 3 1111111 5 2 287 8 OFFICE 3 1111112 9 7 230 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298Esto es lo que quiero mostrar en el DF final:
NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 0 OFFICE 1 2222277 97 167 288 5 OFFICE 2 2222289 9 195 257 7 OFFICE 3 1111111 5 2 287 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298Estaba pensando en resolver esto usando df.itterows()
Esto es lo que he intentado:
for n, v in df.iterrows(): if int(v['Sales']) > 10: calls = df.loc[(v['NAME'] == v) & (int(v['Calls'].max()))] if int(calls['Calls']) > 10: target = df.loc[(v['NAME'] == v) & (int(v['Target'].max()))] else: print("No match found") else: sales = df.loc[(v['NAME'] == v) & (int(v['Sales'].max())] Sin embargo, sigo recibiendo KeyError: False . ¿Alguna idea de lo que estoy haciendo mal?
Esto no está optimizado, pero debería satisfacer sus necesidades. El fragmento de código envía cada grupo de NAME a eval_group() donde verifica el índice más alto para cada columna hasta que se cumplan los criterios de Ventas, Llamadas y Objetivo.
Si tuviera que optimizar, entonces podría aplicar los principios de vectorización o paralelismo a eval_group para que se llame contra todos los grupos a la vez, en lugar de secuencialmente.
Un par de notas, esto devolverá la primera fila si se encuentra una condición de carrera (es decir, varios registros tienen el mismo máximo durante la llamada a idxmax() ). Además, creo en su pregunta, la primera fila en la respuesta deseada debería tener OFFICE 1 siendo la fila 2, no 0.
df = pd.read_csv('./data.txt') def eval_group(df, keys) : for key in keys : row_id = df[key].idxmax() if df.loc[row_id][key] >= 10 or key == keys[-1] : return row_id row_ids = [] keys = ['Sales','Calls','Target'] for name in df['NAME'].unique().tolist() : condition = df['NAME'] == name row_ids.append( eval_group( df[condition], keys) ) df = df[ df.index.isin(row_ids) ] df NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 2 OFFICE 1 2222278 97 167 288 5 OFFICE 2 2222289 9 195 257 7 OFFICE 3 1111111 5 2 287 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298Esto requiere un par de pasos, en los que debe crear marcos de datos intermedios, hacer un condicional y filtrar según el resultado de las condiciones:
temp = (df .drop(columns = 'CUSTOMER_SUPPLIER_NUMBER') .groupby('NAME', sort = False) .idxmax() ) # get the booleans for rows less than 10 bools = df.loc(axis=1)['Sales':'Target'].lt(10) # groupby for each NAME bools = bools.groupby(df.NAME, sort = False).all() # conditions buildup condlist = [~bool_check.Sales, ~bool_check.Calls, ~bool_check.Target] choicelist = [temp.Sales, temp.Calls, temp.Target] # you might have to figure out what to use for default indices = np.select(condlist, choicelist, default = temp.Sales) # get matching rows df.loc[indices] NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 2 OFFICE 1 2222278 97 167 288 5 OFFICE 2 2222289 9 195 257 7 OFFICE 3 1111111 5 2 287 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298