Python 将一定数量的变量从一个组添加到另一个组

Python 将一定数量的变量从一个组添加到另一个组,python,pandas,dataframe,data-wrangling,Python,Pandas,Dataframe,Data Wrangling,我有一个pandas数据框,在该数据框中,我将相同类型的对象分为若干组(例如,3)。例如,组ball_1包含同一类型的3个唯一对象:soccer、basket和bouncy。剩余的对象进入组ball_2,在这种情况下,该组只有一个对象tentiles 对于包含少于3个唯一对象的组,我想用第一个组的前k个唯一对象填充它们。例如,组ball_2将填充网球,然后组ball_1中的足球和篮。因此,目标是使所有组具有相同数量的唯一对象 # chunk into groups of 3 N = 3 g =

我有一个pandas数据框,在该数据框中,我将相同类型的
对象
分为若干组(例如,3)。例如,组
ball_1
包含同一类型的3个唯一对象:
soccer
basket
bouncy
。剩余的对象进入组
ball_2
,在这种情况下,该组只有一个对象
tentiles

对于包含少于3个唯一对象的组,我想用第一个组的前k个唯一对象填充它们。例如,组
ball_2
将填充
网球
,然后组
ball_1
中的
足球
。因此,目标是使所有组具有相同数量的唯一对象

# chunk into groups of 3
N = 3
g = df.groupby('type')['object'].transform(lambda x: pd.factorize(x)[0]) // N + 1
df['group'] = df['type'].str.cat(g.astype(str), '_')

# identify which groups need more objects
for name, batch in df.groupby(['group']):
    subset = df[df.group.isin([name])]
    batch = batch.assign(check = subset['object'].nunique() < 3)
    batch = batch.assign(need = 3 - subset['object'].nunique())
    needmore = batch.loc[batch['check'] == True]
    if needmore.empty:
          continue 
    print('{} needs {} more objects'.format(batch['group'].unique(), batch['need'].unique()))

所需df(已将对象添加到组
ball_2

你可以试试这个:

def addfisrtgroup(x):
    missing=np.arange(3-x.nunique().object)
    typegroup=x.iloc[0,0]
    msk=np.isin(df.loc[df.group.eq(f'{typegroup}_1')].object.factorize()[0],missing)
    return pd.concat([x,df.loc[df.group.eq(f'{typegroup}_1')][msk]])


temp=df.groupby('group')
       .apply(lambda x: addfirstgroup(x) if x.nunique().object<3 else x)
       .drop(columns='group')


groups=temp.index.get_level_values(0).to_frame().reset_index(drop=True)

pd.concat([temp.reset_index(drop=True), groups],1)

不符合条件的组将始终填充第一组?第一组总是符合条件吗?@MrNobody33,是的!我还将它们分块,以便第一个组(如ball_1)具有完整的对象集(因此条件是它包含3个对象)。如果ball_x需要更多的对象,它将被ball_1中的对象填充。如果chair_x需要更多对象,它将由chair_1等填充。刚刚添加了一种方法@psychcoderThis非常适合单独添加
对象
:)谢谢!很抱歉,如果我以前模棱两可(我现在意识到了这一点),那么您能提供一些建议,如何循环您的定义,以便将其推广到所有组吗?例如,如果chair_x需要更多的对象,它将由chair_1填充,等等。在我的示例中,恰好椅子平均分成3个。上面是一个玩具数据集,但我的真实数据集相当大,需要由其
类型的第一组填充多个其他组。但真的非常感谢,再一次!为了再次澄清,当前代码将使用
ball
中的对象填充小于3的任何其他组。但是,我的数据集将包含其他类型,如
table
,当前正在填充
ball\u 1
中的对象,而不是
table\u 1
。谢谢!
typegroup=x.iloc[0,0]
是否依赖于
type
作为df的第一列?您的代码尚未推广到我的真实数据集,但我怀疑这是因为
type
不是第一列。我试图用
typegroup=x.iloc[0,27]
标识正确的列,尽管这不起作用。你有什么建议吗?试试这样:
typegroup=x.reset\u index(drop=True)['type'][0]
     type  object  index    group
0    ball  soccer      1   ball_1
1    ball  soccer      2   ball_1
2    ball  basket      1   ball_1
3    ball  bouncy      1   ball_1
4    ball  tennis      1   ball_2
5    ball  tennis      2   ball_2
6    ball  soccer      1   ball_2
7    ball  soccer      2   ball_2
8    ball  basket      1   ball_2
9    chair office      1  chair_1
10   chair office      2  chair_1
11   chair office      3  chair_1
12   chair lounge      1  chair_1
13   chair dining      1  chair_1
... ...    ...         ......

def addfisrtgroup(x):
    missing=np.arange(3-x.nunique().object)
    typegroup=x.iloc[0,0]
    msk=np.isin(df.loc[df.group.eq(f'{typegroup}_1')].object.factorize()[0],missing)
    return pd.concat([x,df.loc[df.group.eq(f'{typegroup}_1')][msk]])


temp=df.groupby('group')
       .apply(lambda x: addfirstgroup(x) if x.nunique().object<3 else x)
       .drop(columns='group')


groups=temp.index.get_level_values(0).to_frame().reset_index(drop=True)

pd.concat([temp.reset_index(drop=True), groups],1)
     type  object  index    group
0    ball  soccer      1   ball_1
1    ball  soccer      2   ball_1
2    ball  basket      1   ball_1
3    ball  bouncy      1   ball_1
4    ball  tennis      1   ball_2
5    ball  tennis      2   ball_2
6    ball  soccer      1   ball_2
7    ball  soccer      2   ball_2
8    ball  basket      1   ball_2
9   chair  office      1  chair_1
10  chair  office      2  chair_1
11  chair  office      3  chair_1
12  chair  lounge      1  chair_1
13  chair  dining      1  chair_1