我有一个熊猫时间序列,例如:
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'])