我想分享我最终选择的答案,因为它证明了我正在寻找的一般性水平。
import pandas as pd
from itertools import product
dfs = []
step_cols = [col[:-7] for col in df.columns if '_step_n' in col]
const_cols = ([col + '_step' for col in step_cols] + step_cols +
[col + '_step_n' for col in step_cols])
for i, row in df.iterrows():
ranges = []
for col in step_cols:
start = row[col]
stop = row[col] + row[col + '_step'] * row[col + '_step_n']
step = row[col + '_step']
ranges.append(list(range(start, stop, step)))
combos = list(product(*ranges))
dfs.append(pd.DataFrame(
{**{k: v for k, v in zip(step_cols, zip(*combos))},
**df.drop(const_cols, axis=1).iloc[i].to_dict()}))
df2 = pd.concat(dfs, ignore_index=True)
所以如果原来的df是
In [226]: df
Out[226]:
A1 LB7 dF A1_step_n A1_step
0 40000 4 2 2 500
1 60000 6 7 3 300
生成的df2 是
In [227]: df2
Out[227]:
A1 LB7 dF
0 40000 4 2
1 40500 4 2
2 60000 6 7
3 60300 6 7
4 60600 6 7
这还有一个额外的好处,那就是将“_step”和“_step_n”附加到其他列名称允许您遍历笛卡尔积。例如。如果原来的df是
In [230]: df
Out[230]:
A1 LB7 dF A1_step_n A1_step dF_step_n dF_step
0 100 5 15 4 50 2 7
1 200 8 30 3 30 3 4
生成的df2 将遍历A1 和dF
In [231]: df2
Out[231]:
A1 LB7 dF
0 100 5 15
1 100 5 22
2 150 5 15
3 150 5 22
4 200 5 15
5 200 5 22
6 250 5 15
7 250 5 22
8 200 8 30
9 200 8 34
10 200 8 38
11 230 8 30
12 230 8 34
13 230 8 38
14 260 8 30
15 260 8 34
16 260 8 38