将panda数据帧行拆分为多行



我有一个熊猫时间序列,例如:

df = pd.DataFrame(
{
"IDs": [
["A", "B"],
["A", "B", "A", "C"],
["A", "B", "A", "D", "C", "D"],
],
"distance": [[1], [1.1, 2.8], [1, 3, 0.5]],
},
index=[
pd.to_datetime("2022-01-01 12:00:00"),
pd.to_datetime("2022-01-01 12:00:01"),
pd.to_datetime("2022-01-01 12:00:02"),
],
)

这产生:

IDs    distance
2022-01-01 12:00:00 [A, B]  [1]
2022-01-01 12:00:01 [A, B, A, C]    [1.1, 2.8]
2022-01-01 12:00:02 [A, B, A, D, C, D]  [1, 3, 0.5]

我想把行分开,这样每一行只包含到一对的距离,比如:


IDs    distance
2022-01-01 12:00:00 [A, B]  1.0
2022-01-01 12:00:01 [A, B]  1.1
2022-01-01 12:00:01 [A, C]  2.8
2022-01-01 12:00:02 [A, B]  1.0
2022-01-01 12:00:02 [A, D]  3.0
2022-01-01 12:00:02 [C, D]  0.5

最好的方法是什么?

作为信息,每行IDs行总是2n个元素的列表,其中n是对应distance行中的元素数量。

IIUC,使用列表理解将ID按2的块分组,然后explode两个ID/距离列:

df['IDs'] = [[l[i:i+2] for i in range(0,len(l),2)] for l in df['IDs']]
df = df.explode(['IDs', 'distance'])

注意。这要求每行的len(ID(是len(距离(的2倍

输出:

IDs distance
2022-01-01 12:00:00  [A, B]        1
2022-01-01 12:00:01  [A, B]      1.1
2022-01-01 12:00:01  [A, C]      2.8
2022-01-01 12:00:02  [A, B]        1
2022-01-01 12:00:02  [A, D]        3
2022-01-01 12:00:02  [C, D]      0.5

与mozway的答案类似,仅使用numpy整形功能来拆分IDs列表中的值:

df = df.assign(IDs=[np.array(l).reshape(-1, 2) for l in df['IDs'].tolist()]).explode(['IDs', 'distance'])

输出:

>>> df
IDs distance
2022-01-01 12:00:00  [A, B]        1
2022-01-01 12:00:01  [A, B]      1.1
2022-01-01 12:00:01  [A, C]      2.8
2022-01-01 12:00:02  [A, B]        1
2022-01-01 12:00:02  [A, D]        3
2022-01-01 12:00:02  [C, D]      0.5

类似于mozway的解决方案,但让NumPy进行重塑:

df.assign(IDs=df['IDs'].apply(lambda l: np.array(l).reshape(-1, 2))).explode(['IDs', 'distance'])

最新更新