给定段长度和段中的偏移量,如何从 pandas 开始创建偏移量?
How to create offsets from start in pandas, given length of segments and offsets in segment?
标题可能不是最有用的。
我有以下工作代码我想使用本机 pandas.
向量化 [无 for 循环]
基本上,它应该 return 对于每一行它从 0
的累积偏移量,给定每个段的长度,以及该段内的相对偏移量。
import pandas as pd
import numpy as np
df = pd.DataFrame({"id": [0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 9], # notice no 8
"length": [0, 10, 20, 20, 20, 30, 30, 40, 50, 60, 60, 70, 90],
"offset": [0, 0, 1, 3, 4, 0, 7, 0, 0, 0, 1, 0, 0]})
result = np.zeros((len(df),))
current_abs = df.loc[0, "id"]
for i in range(1, len(df)):
if current_abs == df.loc[i, "id"]:
result[i] = result[i - 1]
else:
current_abs = df.loc[i, "id"]
result[i] = result[i - 1] + df.loc[i, "length"]
df["offset_from_start"] = result + df["offset"]
print(df)
id length offset offset_from_start
0 0 0 0 0
1 1 10 0 10
2 2 20 1 31
3 2 20 3 33
4 2 20 4 34
5 3 30 0 60
6 3 30 7 67
7 4 40 0 100
8 5 50 0 150
9 6 60 0 210
10 6 60 1 211
11 7 70 0 280
12 9 90 0 370
这似乎是一个奇特的 cumsum
操作,但我不知道如何有效地做到这一点。
让我们尝试 mask
复制,然后 cumsum:
df['offset_from_start'] = (df['length'].mask(df.duplicated('id'),0)
.cumsum() + df['offset']
)
输出:
id length offset offset_from_start
0 0 0 0 0
1 1 10 0 10
2 2 20 1 31
3 2 20 3 33
4 2 20 4 34
5 3 30 0 60
6 3 30 7 67
7 4 40 0 100
8 5 50 0 150
9 6 60 0 210
10 6 60 1 211
11 7 70 0 280
12 9 90 0 370
另一种方法,原理相同:
df['offset_from_start'] = (~df['id'].duplicated() * df['length']).cumsum() + df['offset']
print(df)
输出
id length offset offset_from_start
0 0 0 0 0
1 1 10 0 10
2 2 20 1 31
3 2 20 3 33
4 2 20 4 34
5 3 30 0 60
6 3 30 7 67
7 4 40 0 100
8 5 50 0 150
9 6 60 0 210
10 6 60 1 211
11 7 70 0 280
12 9 90 0 370
以下是每种方法的时间安排:
%timeit fun_dani_duplicated(df2)
647 µs ± 49.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit fun_quang_hoang(df3)
1.31 ms ± 264 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
标题可能不是最有用的。
我有以下工作代码我想使用本机 pandas.
向量化 [无 for 循环]
基本上,它应该 return 对于每一行它从 0
的累积偏移量,给定每个段的长度,以及该段内的相对偏移量。
import pandas as pd
import numpy as np
df = pd.DataFrame({"id": [0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 9], # notice no 8
"length": [0, 10, 20, 20, 20, 30, 30, 40, 50, 60, 60, 70, 90],
"offset": [0, 0, 1, 3, 4, 0, 7, 0, 0, 0, 1, 0, 0]})
result = np.zeros((len(df),))
current_abs = df.loc[0, "id"]
for i in range(1, len(df)):
if current_abs == df.loc[i, "id"]:
result[i] = result[i - 1]
else:
current_abs = df.loc[i, "id"]
result[i] = result[i - 1] + df.loc[i, "length"]
df["offset_from_start"] = result + df["offset"]
print(df)
id length offset offset_from_start 0 0 0 0 0 1 1 10 0 10 2 2 20 1 31 3 2 20 3 33 4 2 20 4 34 5 3 30 0 60 6 3 30 7 67 7 4 40 0 100 8 5 50 0 150 9 6 60 0 210 10 6 60 1 211 11 7 70 0 280 12 9 90 0 370
这似乎是一个奇特的 cumsum
操作,但我不知道如何有效地做到这一点。
让我们尝试 mask
复制,然后 cumsum:
df['offset_from_start'] = (df['length'].mask(df.duplicated('id'),0)
.cumsum() + df['offset']
)
输出:
id length offset offset_from_start
0 0 0 0 0
1 1 10 0 10
2 2 20 1 31
3 2 20 3 33
4 2 20 4 34
5 3 30 0 60
6 3 30 7 67
7 4 40 0 100
8 5 50 0 150
9 6 60 0 210
10 6 60 1 211
11 7 70 0 280
12 9 90 0 370
另一种方法,原理相同:
df['offset_from_start'] = (~df['id'].duplicated() * df['length']).cumsum() + df['offset']
print(df)
输出
id length offset offset_from_start
0 0 0 0 0
1 1 10 0 10
2 2 20 1 31
3 2 20 3 33
4 2 20 4 34
5 3 30 0 60
6 3 30 7 67
7 4 40 0 100
8 5 50 0 150
9 6 60 0 210
10 6 60 1 211
11 7 70 0 280
12 9 90 0 370
以下是每种方法的时间安排:
%timeit fun_dani_duplicated(df2)
647 µs ± 49.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit fun_quang_hoang(df3)
1.31 ms ± 264 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)