将数据框按行分组保存到恰好两行

saving dataframe groupby rows to exactly two lines

我有一个数据框,我想根据特定列对行进行分组。每组中的行数至少为 4,最多为 50。我想将组中的一列保存为两行。如果 groupsize 是偶数,假设 2n,那么一行中有 n 行,第二行中剩余的 n 行。如果是奇数,n+1nnn+1 都可以。

例如,

import pandas as pd
from io import StringIO

data = """
id,name
1,A
1,B
1,C
1,D
2,E
2,F
2,ds
2,G
2, dsds
"""
df = pd.read_csv(StringIO(data))

我要分组id

df.groupby('id',sort=False)

然后得到一个像

这样的数据框
    id  name
0   1   A B
1   1   C D
2   2   E F ds
3   2   G dsds

这种方法有点复杂,但确实有效;

def func(s: pd.Series):
    mid = max(s.shape[0]//2 ,1)
    l1 = ' '.join(list(s[:mid]))
    l2 = ' '.join(list(s[mid:]))
    return [l1, l2]

df_new = df.groupby('id').agg(func)

df_new["name1"]= df_new["name"].apply(lambda x: x[0])
df_new["name2"]= df_new["name"].apply(lambda x: x[1])


df = df_new.drop(labels="name", axis=1).stack().reset_index().drop(labels = ["level_1"], axis=1).rename(columns={0:"name"}).set_index("id")

可能不是最有效的解决方案,但它有效:

import numpy as np

df = df.sort_values('id')
# next 3 lines: for each group find the separation
df['range_idx'] = range(0, df.shape[0])
df['mean_rank_group'] = df.groupby(['id'])['range_idx'].transform(np.mean)
df['separate_column'] = df['range_idx'] < df['mean_rank_group']

# groupby itself with the help of additional column
df.groupby(['id', 'separate_column'], as_index=False)['name'].agg(','.join).drop(
    columns='separate_column')