Python 有没有办法将DataFrame中的重复行作为新列附加到右侧?
我有一个数据集,其中一列中包含重复的行,但其他列中包含不同的值。我需要合并这些重复的行,同时保留每行的值。请参见下面的示例,其中“ID”列中有重复的值Python 有没有办法将DataFrame中的重复行作为新列附加到右侧?,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个数据集,其中一列中包含重复的行,但其他列中包含不同的值。我需要合并这些重复的行,同时保留每行的值。请参见下面的示例,其中“ID”列中有重复的值 data={'ID':['01.560','05.890','05.890','02.564'],'Foo':[1,4,7,6],'Ba':['cat','dog','rabbit','monkey'],'Bar':[5.76,9.99,1.20,7.19]} df=pd.DataFrame(data) output: ID
data={'ID':['01.560','05.890','05.890','02.564'],'Foo':[1,4,7,6],'Ba':['cat','dog','rabbit','monkey'],'Bar':[5.76,9.99,1.20,7.19]}
df=pd.DataFrame(data)
output:
ID Foo Ba Bar
0 01.560 1 cat 5.76
1 05.890 4 dog 9.99
2 05.890 7 rabbit 1.20
3 02.564 6 monkey 7.19
我需要的是将具有重复ID的行与新列一起向右移动(可能带有一些前缀以确保列名称是唯一的)。所需输出为:
Foo Ba Bar Foo1 Ba1 Bar1
ID
01.560 1 cat 5.76 NaN NaN NaN
05.890 4 dog 9.99 7 rabbit 1.20
02.564 6 monkey 7.19 NaN NaN NaN
我尝试将重复的行追加到dict,然后从该dict生成新的数据帧,并追加到原始数据帧。然而,这种方法非常慢,我想知道是否有更直接的方法来实现这一点
def singl_line(ID,df):
line_num = 1
results=dict()
for i in range(len(df.loc[df['ID'] == ID])):
fll=df.to_dict('records')[df.loc[df['ID'] == ID].index[i]]
numbered=dict(("{} {}".format(k,line_num),v) for k,v in fll.items())
line_num+=1
results.update(numbered)
continue
return results
df_1ln=pd.DataFrame()
full=df['ID'].tolist()
nodup = []
for i in full:
if i not in nodup:
nodup.append(i)
continue
nodup
for i in nodup:
temp=pd.DataFrame([singl_line(i,df)],columns=singl_line(i,df).keys())
df_1ln=df_1ln.append(temp,sort=False)
continue
df_1ln
output:
ID 1 Foo 1 Ba 1 Bar 1 ID 2 Foo 2 Ba 2 Bar 2
0 01.560 1 cat 5.76 NaN NaN NaN NaN
0 05.890 4 dog 9.99 05.890 7.0 rabbit 1.2
0 02.564 6 monkey 7.19 NaN NaN NaN NaN
我正在使用的数据集大约有4000行和150列,每个ID大约有10个副本,因此我正在寻找一种比上面的方法更快的方法。这解决了您的请求;你必须测试它,看看它是否可扩展
M = df.loc[df.duplicated('ID')].add_suffix('_1').set_index('ID_1')
orig = df.drop_duplicates('ID').set_index('ID')
pd.concat([orig,M],axis=1)
Foo Ba Bar Foo_1 Ba_1 Bar_1
01.560 1 cat 5.76 NaN NaN NaN
05.890 4 dog 9.99 7.0 rabbit 1.2
02.564 6 monkey 7.19 NaN NaN NaN
获取重复值的数据帧,并在列轴上与重复自由值的数据帧连接。请注意,索引设置为“ID”另一种方法是使用
pivot
(不过您必须重新组织列):
自联接将很好地工作,回答如下&在这个问题中:
谢谢工作完美。我以前的方法需要一个多小时才能处理,这个方法几乎是即时的:)
result = (df.assign(count=df.groupby("ID").cumcount())
.pivot(index='ID', columns='count'))
result.columns = ["_".join(str(x) for x in i) for i in result.columns]
print (result)
Foo_0 Foo_1 Ba_0 Ba_1 Bar_0 Bar_1
ID
01.560 1.0 NaN cat NaN 5.76 NaN
02.564 6.0 NaN monkey NaN 7.19 NaN
05.890 4.0 7.0 dog rabbit 9.99 1.2
df.join(df.drop('ID', 1), on='ID', rsuffix='1')