python pandas dataframe argmax

python - Encuentre la primera y última columna distinta de cero en cada fila de un marco de datos de pandas



dataframe argmax (4)

Tengo DataFrame en vista de Name y Date con valores de peso en celdas:

Name Jan17 Jun18 Dec18 Apr19 count Nick 0 1.7 3.7 0 2 Jack 0 0 2.8 3.5 2 Fox 0 1.7 0 0 1 Rex 1.0 0 3.0 4.2 3 Snack 0 0 2.8 4.4 2 Yosee 0 0 0 4.3 1 Petty 0.5 1.3 2.8 3.5 4

Start y Finish deben agregarse al marco de datos en referencia a la siguiente definición:

  1. Start primer valor que no sea cero en la fila que comenzó desde la columna del Jan17 de Jan17 al Apr19 de Apr19
  2. Finish primer valor no cero en secuencia del Apr19 de Jan17 al Jan17 de Jan17

Además, si la fila tiene solo un valor distinto de cero en la fila, entonces Start y Finish son los mismos.

Para encontrar el primer elemento no cero en la fila, probé data[col].keys, np.argmax() y funciona como se esperaba.

date_col_list = [''Jan17'',''Jun18'',''Dec18'', ''Apr19'']

data[''Start'']=data[date_col_list].keys([np.argmax(data[date_col_list].values!=0, axis=1)]

El resultado es:

Name Jan17 Jun18 Dec18 Apr19 count Start Nick 0 1.7 3.7 0 2 Jun18 Jack 0 0 2.8 3.5 2 Dec18 Fox 0 1.7 0 0 1 Jun18 Rex 1.0 0 3.0 4.2 3 Jan18 Snack 0 0 2.8 4.4 2 Dec18 Yosee 0 0 0 4.3 1 Apr19 Petty 0.5 1.3 2.8 3.5 4 Jan17

Para detectar valores para la columna Finish , intenté usar: np.apply_along_axis como: def func_X(i): return np.argmax(np.where(i!=0))

np.apply_along_axis(func1d = func_X, axis=1, arr=data[date_col_list].values)

El resultado es error: ''tuple'' object has no attribute ''argmax''

El marco de datos esperado es:

Name Jan17 Jun18 Dec18 Apr19 count Start Finish Nick 0 1.7 3.7 0 2 Jun18 Dec18 Jack 0 0 2.8 3.5 2 Dec18 Apr19 Fox 0 1.7 0 0 1 Jun18 Jun18 Rex 1.0 0 3.0 4.2 3 Jan18 Apr19 Snack 0 0 2.8 4.4 2 Dec18 Apr19 Yosee 0 0 0 4.3 1 Apr19 Apr19 Petty 0.5 1.3 2.8 3.5 4 Jan17 Apr19

¿Cómo puedo encontrar Finish en referencia a un valor distinto de cero en la dirección desde la última columna ( Apr19 ) hasta la primera ( Jan17 )?


idxmax

mask = df.drop([''Name'', ''count''], axis=1) > 0 df.assign(start=mask.idxmax(axis=1), end=mask.iloc[:,::-1].idxmax(axis=1)) Name Jan17 Jun18 Dec18 Apr19 count start end 0 Nick 0.0 1.7 3.7 0.0 2 Jun18 Dec18 1 Jack 0.0 0.0 2.8 3.5 2 Dec18 Apr19 2 Fox 0.0 1.7 0.0 0.0 1 Jun18 Jun18 3 Rex 1.0 0.0 3.0 4.2 3 Jan17 Apr19 4 Snack 0.0 0.0 2.8 4.4 2 Dec18 Apr19 5 Yosee 0.0 0.0 0.0 4.3 1 Apr19 Apr19 6 Petty 0.5 1.3 2.8 3.5 4 Jan17 Apr19

idxmax columnas irrelevantes, luego use idxmax primero en las columnas, luego en las columnas invertidas para encontrar el primero y el último índice válido respectivamente.


first_valid_index y last_valid_index

d = df.mask(df == 0).drop([''Name'', ''count''], 1) df.assign( Start=d.apply(pd.Series.first_valid_index, 1), Finish=d.apply(pd.Series.last_valid_index, 1) ) Name Jan17 Jun18 Dec18 Apr19 count Start Finish 0 Nick 0.0 1.7 3.7 0.0 2 Jun18 Dec18 1 Jack 0.0 0.0 2.8 3.5 2 Dec18 Apr19 2 Fox 0.0 1.7 0.0 0.0 1 Jun18 Jun18 3 Rex 1.0 0.0 3.0 4.2 3 Jan17 Apr19 4 Snack 0.0 0.0 2.8 4.4 2 Dec18 Apr19 5 Yosee 0.0 0.0 0.0 4.3 1 Apr19 Apr19 6 Petty 0.5 1.3 2.8 3.5 4 Jan17 Apr19

stack entonces groupby

d = df.mask(df == 0).drop([''Name'', ''count''], 1) def fl(s): return s.xs(s.name).index[[0, -1]] s, f = d.stack().groupby(level=0).apply(fl).str df.assign(Start=s, Finish=f) Name Jan17 Jun18 Dec18 Apr19 count Start Finish 0 Nick 0.0 1.7 3.7 0.0 2 Jun18 Dec18 1 Jack 0.0 0.0 2.8 3.5 2 Dec18 Apr19 2 Fox 0.0 1.7 0.0 0.0 1 Jun18 Jun18 3 Rex 1.0 0.0 3.0 4.2 3 Jan17 Apr19 4 Snack 0.0 0.0 2.8 4.4 2 Dec18 Apr19 5 Yosee 0.0 0.0 0.0 4.3 1 Apr19 Apr19 6 Petty 0.5 1.3 2.8 3.5 4 Jan17 Apr19


En tu caso prueba algo diferente con dot

s=df.loc[:,''Jan17'':''Apr19''].ne(0) s=s.dot(s.columns+'','').str[:-1].str.split('','') s.str[0],s.str[-1] Out[899]: (0 Jun18 1 Dec18 2 Jun18 3 Jan17 4 Dec18 5 Apr19 6 Jan17 dtype: object, 0 Dec18 1 Apr19 2 Jun18 3 Apr19 4 Apr19 5 Apr19 6 Apr19 dtype: object) #df[''Start''],df[''End'']=s.str[0],s.str[-1]


Usando cumsum en la array subyacente

m = df.drop([''Name'', ''count''], axis=1) u = m.to_numpy().cumsum(1) start = (u!=0).argmax(1) end = u.argmax(1) df.assign(start=m.columns[start], end=m.columns[end])

Name Jan17 Jun18 Dec18 Apr19 count start end 0 Nick 0.0 1.7 3.7 0.0 2 Jun18 Dec18 1 Jack 0.0 0.0 2.8 3.5 2 Dec18 Apr19 2 Fox 0.0 1.7 0.0 0.0 1 Jun18 Jun18 3 Rex 1.0 0.0 3.0 4.2 3 Jan17 Apr19 4 Snack 0.0 0.0 2.8 4.4 2 Dec18 Apr19 5 Yosee 0.0 0.0 0.0 4.3 1 Apr19 Apr19 6 Petty 0.5 1.3 2.8 3.5 4 Jan17 Apr19