Semua jawaban yang diberikan sejauh ini menghasilkan perilaku yang berpotensi berbahaya karena sangat mungkin Anda memilih nilai dummy yang sebenarnya merupakan bagian dari dataset. Ini semakin mungkin karena Anda membuat grup dengan banyak atribut. Sederhananya, pendekatan itu tidak selalu digeneralisasi dengan baik.
Pemecahan yang kurang rumit adalah dengan menggunakan pd.drop_duplicates () untuk membuat indeks kombinasi nilai yang unik, masing-masing dengan ID mereka sendiri, dan kemudian mengelompokkan pada id itu. Itu lebih verbose tetapi menyelesaikan pekerjaan:
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]
Perhatikan bahwa Anda sekarang dapat melakukan hal berikut:
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')]))
Ini akan mengembalikan hasil yang sukses tanpa harus khawatir menimpa data nyata yang keliru sebagai nilai dummy.