我有一个形状为(12000, 21)的DataFrame,内容如下:
id CID U_lot P4 P5 P6 P7 P8 P9 0 A0694 M 0 1 0 1 1 0 1 A1486 M 0 0 1 0 0 0 2 C0973 S 0 1 1 0 0 0 3 B4251 D 0 0 0 1 0 1 4 I0041 S 1 0 0 1 1 0 5 J1102 F 0 0 0 0 0 1
如何将DataFrame转换成如下格式:
id CID U_lot P_lots Label 0 A0694 M [P5,P7] P8 1 A0694 M [P5,P8] P7 2 A0694 M [P7,P8] P5 3 A1486 M NAN P6 4 C0973 S [P5] P6 5 C0973 S [P6] P5 6 B4251 D [P7] P8 7 B4251 D [P8] P7 8 I0041 S [P4,P7] P8 9 I0041 S [P4,P8] P710 I0041 S [P7,P8] P411 J1102 F NAN P9
我尝试过逆转pd.get_dummies,但似乎不起作用。
回答:
获取list
列真的会大大降低效率。但如果这是必要的,首先使用stack
(或melt
)将DataFrame转换为长格式。在这一步中,也要记录我们最终输出中需要的所有行(这是为了稍后获取那些NaN
行)。
df1 = (df.set_index(['id', 'CID', 'U_lot']) .stack() .loc[lambda x: x!=0] .reset_index(-1) .drop(columns=0) .rename(columns={'level_3': 'Label'}))idx = df1.set_index('Label', append=True).index
然后,我们将这个长格式的DataFrame与其自身合并,以便获取所有的'P_lots'
,并使用query
排除被拆分出的标签。
df1 = (df1.merge(df1, left_index=True, right_index=True, suffixes=['', '_r']) .query('Label != Label_r'))
最后,使用groupby
获取列表,并通过reindex
重新获取NaN
值
df1 = (df1.groupby(['id', 'CID', 'U_lot', 'Label']) .agg(P_lot=('Label_r', list)) .reindex(idx) .reset_index())
id CID U_lot Label P_lot0 0 A0694 M P5 [P7, P8]1 0 A0694 M P7 [P5, P8]2 0 A0694 M P8 [P5, P7]3 1 A1486 M P6 NaN4 2 C0973 S P5 [P6]5 2 C0973 S P6 [P5]6 3 B4251 D P7 [P9]7 3 B4251 D P9 [P7]8 4 I0041 S P4 [P7, P8]9 4 I0041 S P7 [P4, P8]10 4 I0041 S P8 [P4, P7]11 5 J1102 F P9 NaN