Tengo un marco de datos de pandas, df:

id year variable value
1   19   high     20
1   19   low      10
1   20   high     20
1   20   low      30

Quiero agrupar por id y año (cada grupo tendrá solo 2 filas, una para alto y otro para bajo), y verificar si el valor de la variable alta es realmente mayor que el de la variable baja o no. Y si no, quiero eliminar dichos grupos y ponerlos en un nuevo marco de datos. Entonces, para arriba, quiero tener, df:

id year variable value
1   19   high     20
1   19   low      10

Y df2:

id year variable value
1   20   high     20
1   20   low      30
0
Ank 26 jun. 2020 a las 12:28

3 respuestas

Recrea tu DataFrame

df = pd.DataFrame(
    {
        "id": 1,
        "year": [19, 19, 20, 20],
        "variable": ["high", "low", "high", "low"],
        "value": [20, 10, 20, 30],
    }
)

Iterar a través de grupos por grupos y filtrar:

df_res = []
df_res2 = []
for _, df_group in df.groupby(["id", "year"]):

    val_low = df_group.query("variable == 'low'").value.values[0]
    val_high = df_group.query("variable == 'high'").value.values[0]

    if val_high > val_low:
        df_res.append(df_group)
    else:
        df_res2.append(df_group)

df_res = pd.concat(df_res)
df_res2 = pd.concat(df_res2)

print(df_res)
id year variable value
1   19   high     20
1   19   low      10

print(df_res2)
id year variable value
1   20   high     20
1   20   low      30
0
zuecho 26 jun. 2020 a las 09:49

De una principiante:

Cree 2 df que contendrán los valores "variables" altos y bajos:

dfh = df[df["var"]=="high"]
dfh.reset_index(drop=True, inplace=True)

dfl = df[df["var"]=="low"]
dfl.reset_index( drop=True, inplace=True)

Haga sus comprobaciones y ponga el resultado en una nueva columna:

dfh['greatest'] = np.where(dfh['val'] > dfl['val'], 'True', 'False')
dfl['greatest'] = np.where(dfl['val'] < dfh['val'], 'True', 'False')

Combina esos dos dfs:

dfall = pd.concat([dfh,dfl])

Finalmente, cree los dfs seleccionando los valores interesantes:

df_great = dfall[dfall["greatest"]=="True"]
df_less = dfall[dfall["greatest"]=="False"]
0
CornelioQuinto 26 jun. 2020 a las 10:20

El siguiente código lo resolverá sin necesidad de groupby. en su lugar, pivota la variable, luego compara alto y bajo manteniendo solo aquellas columnas donde alto> bajo, y nuevamente las separa

df.pivot_table(index=['id','year'],columns='variable', values='value').reset_index().query('high>low').melt(id_vars=['id','year'],value_vars=['high','low'])

id  year    variable    value
0   1   19  high    20
1   1   19  low     10

El segundo marco de datos solo reemplazará high>low con low>=high

1
Yati Raj 26 jun. 2020 a las 09:40