Извините - меня уже потянуло на собрание: вот как бы я справился с этим:
df1 = df.groupby([df.index, "ID"]).agg(
lambda x: x.replace(0, np.nan).dropna().tolist())
# Create a sum of each list
df1['list_'] = df1.sum(axis=1)
print(df1['list_'])
0 [2.5, 18]
1 [4.0, 18]
2 [3.0, 78, 1]
3 [4.0, 21, 7, 8, 10, 30, 40, 20]
4 [3.0, 18]
5 [2.0, 18, 80, 10, 11, 8]
6 [3.5, 18, 9, 10]
Name: list_, dtype: object
Затем создайте наш столбец счетчика с cumcount и pivot, используя кросс-таблицу.
# Create a row to use for columns
df1['count'] = 'H' + (df1.groupby('ID').cumcount() + 1).astype(str)
df1.reset_index(level=1,inplace=True)
final_ = pd.crosstab(df1["ID"],
df1["count"],
values=df1["list_"],
aggfunc="first").reset_index()
print(final_)
ID H1 H2
0 1 [2.5, 18] [4.0, 21, 7, 8, 10, 30, 40, 20]
1 4 [4.0, 18] NaN
2 7 [3.0, 78, 1] [2.0, 18, 80, 10, 11, 8]
3 21 [3.0, 18] NaN
4 41 [3.5, 18, 9, 10] NaN
Единственная болевая точка, которую я вижу при этом, состоит в том, что мой столбец list_ является объектом, неуверенным, будете ли вы выполнять дальнейшие операции с ним позже. Решение Jezrael будет более подходящим, если так.
Отредактируйте для всех, кто сталкивался с этим:
использование python's .sum()
является одним из самых медленных методов для конкатенации списков, если производительность вызывает беспокойство, см. Как сделатьплоский список из списка списков