Alle bisher gegebenen Antworten führen zu potenziell gefährlichem Verhalten, da Sie möglicherweise einen Dummy-Wert auswählen, der tatsächlich Teil des Datensatzes ist. Dies wird immer wahrscheinlicher, wenn Sie Gruppen mit vielen Attributen erstellen. Einfach ausgedrückt, der Ansatz lässt sich nicht immer gut verallgemeinern.
Eine weniger hackige Lösung besteht darin, mit pd.drop_duplicates () einen eindeutigen Index von Wertekombinationen mit jeweils eigener ID zu erstellen und diese dann zu gruppieren. Es ist ausführlicher, erledigt aber die Arbeit:
def safe_groupby(df, group_cols, agg_dict):
# set name of group col to unique value
group_id = 'group_id'
while group_id in df.columns:
group_id += 'x'
# get final order of columns
agg_col_order = (group_cols + list(agg_dict.keys()))
# create unique index of grouped values
group_idx = df[group_cols].drop_duplicates()
group_idx[group_id] = np.arange(group_idx.shape[0])
# merge unique index on dataframe
df = df.merge(group_idx, on=group_cols)
# group dataframe on group id and aggregate values
df_agg = df.groupby(group_id, as_index=True)\
.agg(agg_dict)
# merge grouped value index to results of aggregation
df_agg = group_idx.set_index(group_id).join(df_agg)
# rename index
df_agg.index.name = None
# return reordered columns
return df_agg[agg_col_order]
Beachten Sie, dass Sie jetzt einfach Folgendes tun können:
data_block = [np.tile([None, 'A'], 3),
np.repeat(['B', 'C'], 3),
[1] * (2 * 3)]
col_names = ['col_a', 'col_b', 'value']
test_df = pd.DataFrame(data_block, index=col_names).T
grouped_df = safe_groupby(test_df, ['col_a', 'col_b'],
OrderedDict([('value', 'sum')]))
Dadurch wird das erfolgreiche Ergebnis zurückgegeben, ohne dass Sie sich Gedanken über das Überschreiben realer Daten machen müssen, die als Dummy-Wert verwechselt werden.