pandas Panda将多行合并为一行,不同的列名不在一列中

thtygnil  于 2023-04-18  发布在  其他
关注(0)|答案(2)|浏览(202)

我有一个csv文件-
CSV A-

Date/Time             Num
2023/04/10 14:13:18      6122
2023/04/10 14:14:24      6005
2023/04/10 14:14:59      6004

最多有3行或更少,Num=6122也总是在那里。其他两个数字(6005和6004)行可能在那里,也可能不在那里。
我正在寻找的输出-

Date/Time             Num       Date/Time_1          Num_1      Date/Time_2          Num_2
2023/04/10 14:13:18      6122   2023/04/10 14:14:24      6005   2023/04/10 14:14:59      6004

如果Num=6005,则日期/时间和数字应在第3列和第4列,如果Num=6004,则日期/时间和数字应在第5列和第6列,否则留空,如下所示-

Date/Time             Num       Date/Time_1      Num_1        Date/Time_2           Num_2
2023/04/10 14:13:18      6122                                   2023/04/10 14:14:59      6004
4c8rllxm

4c8rllxm1#

你可以先转换stack,然后再转换to_frametransposeswaplevel。最后将MultiIndex变平:

out = df.stack().to_frame().T.swaplevel(axis=1)

out.columns = out.columns.map(lambda x: f'{x[0]}_{x[1]}')

输出:

Date/Time_0 Num_0          Date/Time_1 Num_1          Date/Time_2 Num_2
0  2023/04/10 14:13:18  6122  2023/04/10 14:14:24  6005  2023/04/10 14:14:59  6004

如果你不想要_0

out.columns = out.columns.map(lambda x: f'{x[0]}{"_"+str(x[1]) if x[1] else ""}')

输出:

Date/Time   Num          Date/Time_1 Num_1          Date/Time_2 Num_2
0  2023/04/10 14:13:18  6122  2023/04/10 14:14:24  6005  2023/04/10 14:14:59  6004
强制特定顺序,并根据需要插入NaN

假设此输入:

Date/Time   Num
0  2023/04/10 14:13:18  6122
1  2023/04/10 14:14:59  6004

在应用上述方法之前,您可以使用字典和reindex强制重新索引:

order = [6122, 6005, 6004]

d = {k: v for v,k in enumerate(order)}

out = (df.set_axis(df['Num'].map(d)).reindex(d.values())
         .stack(dropna=False).to_frame().T.swaplevel(axis=1)
      )
out.columns = out.columns.map(lambda x: f'{x[0]}{"_"+str(x[1]) if x[1] else ""}')

输出:

Date/Time     Num Date/Time_1 Num_1          Date/Time_2   Num_2
0  2023/04/10 14:13:18  6122.0         NaN   NaN  2023/04/10 14:14:59  6004.0
gojuced7

gojuced72#

可以使用numpy.ravel

import numpy as np

cols = np.ravel([df.columns + (f'_{i}' if i else '') for i in range(len(df))])
out = pd.DataFrame([np.ravel(df)], columns=cols)

输出:

>>> out
             Date/Time   Num          Date/Time_1  Num_1          Date/Time_2  Num_2
0  2023/04/10 14:13:18  6122  2023/04/10 14:14:24   6005  2023/04/10 14:14:59   6004

更新

如果数字6005不在那里,在这种情况下,它将在第3和第4列设置6004数字行,但我希望它是第5和第6列,第3-第4列将是空的?
您可以硬编码转换:

pd.concat([df[df['Num'] == 6122].reset_index(drop=True),
           df[df['Num'] == 6005].add_suffix('_1').reset_index(drop=True),
           df[df['Num'] == 6004].add_suffix('_2').reset_index(drop=True)], axis=1)

# Output
             Date/Time   Num Date/Time_1  Num_1          Date/Time_2  Num_2
0  2023/04/10 14:13:18  6122         NaN    NaN  2023/04/10 14:14:59   6004

要将此行注入数据库,可以尝试使用以下命令将NaT/NaN转换为None:

# out = pd.concat(...)
out = out.replace({pd.NaT: None, np.NaN: None})

相关问题