根据条件重复行并交换聚集

时间:2019-06-07 10:22:59

标签: python-3.x pandas

我有下表:

    name    a0  a1  type    val
0   name1   1   0   AB     100
1   name1   2   0   AB     105
2   name2   1   2   BB     110
3   name3   1   0   AN     120

我想这样做。

对于每种类型,我看到类型名称中不包含相同的2个字母,我想复制该行并交换a0和a1列以及类型列的字母。因此,我的结果将是:

     name   a0  a1  type    val
0   name1   1   0   AB     100
1   name1   0   1   BA     100
2   name1   2   0   AB     105
3   name1   0   2   BA     105
4   name2   1   2   BB     110
5   name3   1   0   AN     120
6   name3   0   1   NA     120

请注意,例如,对于相同的名称,我们可以具有相同的类型,但a0和a1(以及val)不同。

因此,我们可以像原始表的前两行一样使用name1并键入AB。

我尝试过:

df1 = pd.DataFrame({'name':['name1', 'name1', 'name2', 'name3'], 'a0':[1, 2, 1, 1], 'a1':[0, 0, 2, 0], 'type':['AB', 'AB', 'BB', 'AN'], 'val':[100,105, 110, 120]})


for idx in df1.index:

    a1 = df1.loc[idx, 'a0']
    a0 = df1.loc[idx, 'a1']
    val = df1.loc[idx, 'val']
    name = df1.loc[idx, 'name']

    if df1.loc[idx, 'type'] == 'AB':
        new_type = 'BA'

    elif df1.loc[idx, 'type'] == 'AN':
        new_type = 'NA'

    row = pd.DataFrame({'name':name, 'a0':a0 , 'a1':a1 , 'type':new_type, 'val':val}, index=np.arange(idx))
    df1 = df1.append(row, ignore_index=False)
    df1 = df1.sort_index().reset_index(drop=True)

但是它给了我

    name    a0  a1  type    val
0   name1   1   0   AB     100
1   name1   2   0   BA     105
2   name1   0   2   BA     105
3   name1   2   0   BA     105
4   name1   0   2   BA     105
5   name1   2   0   BA     105
6   name1   0   2   BA     105
7   name1   2   0   AB     105
8   name2   1   2   BB     110
9   name3   1   0   AN     120

2 个答案:

答案 0 :(得分:3)

首先创建掩码以标识具有2个不同字母的值,然后通过DataFrame.assign创建新的DataFrame,在列中交换值,连接在一起并按索引排序,最后创建默认索引值:

mask = df['type'].apply(set).str.len() == 2

df1 = df[mask].assign(type=lambda x: df['type'].str[1] + df['type'].str[0])
df1[['a0','a1']] = df1[['a1','a0']].to_numpy()
#pandas below
#df1[['a0','a1']] = df1[['a1','a0']].values

df = pd.concat([df, df1]).sort_index().reset_index(drop=True)
print (df)
    name  a0  a1 type  val
0  name1   1   0   AB  100
1  name1   0   1   BA  100
2  name1   2   0   AB  105
3  name1   0   2   BA  105
4  name2   1   2   BB  110
5  name3   1   0   AN  120
6  name3   0   1   NA  120

答案 1 :(得分:2)

您可以使用:

def myfunc(x):
    x['type']=x['type'][::-1]
    x[['a0','a1']]=x[['a1','a0']].values
    return x

m=df.type.apply(set).str.len().gt(1)
pd.concat([df,df.loc[m].apply(myfunc,axis=1)],ignore_index=True).sort_values(['name','val'])

    name  a0  a1 type  val
0  name1   1   0   AB  100
4  name1   0   1   BA  100
1  name1   2   0   AB  105
5  name1   0   2   BA  105
2  name2   1   2   BB  110
3  name3   1   0   AN  120
6  name3   0   1   NA  120