我正在尝试制作一个Python程序,它将根据公式、给定因素和输入数据帧计算结果。
N_cars我在给定的道路长度 ( ) 上有许多汽车 ( l) 及其平均速度 ( v):
input_columns = ['l', 'N_cars', 'v']
input_data = [[3.5, 1000, 100], [5.7, 500, 110],
[10, 367, 110], [11.1, 1800, 95],
[2.8, 960, 105], [4.7, 800, 120],
[10.4, 103, 111], [20.1, 1950, 115]]
input_df = pd.DataFrame(input_data, columns=input_columns)
input_df
l N_cars v
0 3.5 1000 100
1 5.7 500 110
2 10.0 367 110
3 11.1 1800 95
4 2.8 960 105
5 4.7 800 120
6 10.4 103 111
7 20.1 1950 115
Run Code Online (Sandbox Code Playgroud)
我还知道每个类别汽车的公式所需的因素,并且我知道每个类别的百分比。我还为每个类别提供了不同的选项(我这里的 3 个选项只是一个示例,还有更多选项)。
factors_columns = ['category', 'category %', 'option', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
factors_data = [['A', 58, 'opt_1', 0.000011, 0.23521, 0.93847, 0.39458, 0.00817, 0.24566, 0.0010, 0],
['A', 58, 'opt_2', 0.000011, 0.23521, 0.93145, 0.39458, 0.00467, 0.24566, 0.0010, 0],
['A', 58, 'opt_3', 0.000011, 0.23521, 0.93145, 0.39458, 0.00467, 0.24566, 0.0010, 0],
['B', 22, 'opt_1', 0.002452, 0.48327, 0.83773, 0.92852, 0.00871, 0.29568, 0.0009, 0.02],
['B', 22, 'opt_2', 0.002899, 0.49327, 0.83773, 0.92852, 0.00871, 0.30468, 0.0009, 0.02],
['B', 22, 'opt_3', 0.002452, 0.48327, 0.83773, 0.92852, 0.00771, 0.29568, 0.0119, 0.01],
['C', 17, 'opt_1', 0.082583, 0.39493, 0.02462, 0.82714, 0.00918, 0.28572, 0.0012, 0],
['C', 17, 'opt_2', 0.072587, 0.35493, 0.02852, 0.82723, 0.00912, 0.29572, 0.0018, 0],
['C', 17, 'opt_3', 0.082583, 0.39493, 0.02852, 0.82714, 0.00962, 0.28572, 0.0012, 0.01],
['D', 3, 'opt_1', 0.018327, 0.32342, 0.82529, 0.92752, 0.00988, 0.21958, 0.0016, 0],
['D', 3, 'opt_2', 0.014427, 0.32342, 0.82729, 0.92752, 0.00968, 0.22558, 0.0026, 0],
['D', 3, 'opt_3', 0.018327, 0.32342, 0.82729, 0.94452, 0.00988, 0.21258, 0.0016, 0]]
factors_df = pd.DataFrame(factors_data, columns=factors_columns)
factors_df
category category % option a b c d e f g h
0 A 58 opt_1 0.000011 0.23521 0.93847 0.39458 0.00817 0.24566 0.0010 0.00
1 A 58 opt_2 0.000011 0.23521 0.93145 0.39458 0.00467 0.24566 0.0010 0.00
2 A 58 opt_3 0.000011 0.23521 0.93145 0.39458 0.00467 0.24566 0.0010 0.00
3 B 22 opt_1 0.002452 0.48327 0.83773 0.92852 0.00871 0.29568 0.0009 0.02
4 B 22 opt_2 0.002899 0.49327 0.83773 0.92852 0.00871 0.30468 0.0009 0.02
5 B 22 opt_3 0.002452 0.48327 0.83773 0.92852 0.00771 0.29568 0.0119 0.01
6 C 17 opt_1 0.082583 0.39493 0.02462 0.82714 0.00918 0.28572 0.0012 0.00
7 C 17 opt_2 0.072587 0.35493 0.02852 0.82723 0.00912 0.29572 0.0018 0.00
8 C 17 opt_3 0.082583 0.39493 0.02852 0.82714 0.00962 0.28572 0.0012 0.01
9 D 3 opt_1 0.018327 0.32342 0.82529 0.92752 0.00988 0.21958 0.0016 0.00
10 D 3 opt_2 0.014427 0.32342 0.82729 0.92752 0.00968 0.22558 0.0026 0.00
11 D 3 opt_3 0.018327 0.32342 0.82729 0.94452 0.00988 0.21258 0.0016 0.00
Run Code Online (Sandbox Code Playgroud)
对于每个选项(opt_1、opt_2、opt_3),我必须根据以下公式计算结果(因子取自因子表,但 v 来自输入表):
formula = ( (a*v*v) + (b*v) + c + (d/v) ) / ( (e*v*v) + (f*v) + g) * (1 - h)
result = l * N_cars * formula
Run Code Online (Sandbox Code Playgroud)
但是,我必须考虑到每种汽车类别的百分比。对于每一行,input_df我必须执行计算三次,三个选项各执行一次。例如,对于 的索引 0 input_df,我有N_cars=1000、v=100和l=3.5,输出应如下所示:
# for opt_1:
result = 3.5 * 1000 * ((58% of category A {formula for index 0 of factors_df}) +
(22% of category B {formula for index 3 of factors_df) +
(17% of category C {formula for index 6 of factors_df}) +
(3% of category D {formula for index 9 of factors_df}) )
# for opt_2:
result = 3.5 * 1000 * ((58% of category A {formula for index 1 of factors_df}) +
(22% of category B {formula for index 4 of factors_df) +
(17% of category C {formula for index 7 of factors_df}) +
(3% of category D {formula for index 10 of factors_df}) )
# for opt_3:
result = 3.5 * 1000 * ((58% of category A {formula for index 2 of factors_df}) +
(22% of category B {formula for index 5 of factors_df) +
(17% of category C {formula for index 8 of factors_df}) +
(3% of category D {formula for index 11 of factors_df}) )
Run Code Online (Sandbox Code Playgroud)
因此,作为输出,对于 中的每一行input_df,我应该有三个结果,三个选项各一个。
我可以为每个步骤手动进行计算,但我遇到的麻烦是创建一个循环,自动为每个输入行和所有 3 个选项执行计算,然后传递到下一个输入行,依此类推,直到最后一个输入行。
不确定您的预期结果是什么,但我相信这符合您的要求:
def formula(g, *, l, N_cars, v):
x = (1 - g.h) * (g.a * v*v + g.b*v + g.c + g.d/v) / (g.e * v*v + g.f*v + g.g)
return N_cars * l * (x * g.pct / 100).sum()
groups = factors_df.rename(columns={"category %": "pct"}).groupby("option")
result = input_df.apply(lambda r: groups.apply(lambda g: formula(g, **r)), axis=1)
Run Code Online (Sandbox Code Playgroud)
输出:
In [5]: input_df.join(result)
Out[5]:
l N_cars v opt_1 opt_2 opt_3
0 3.5 1000 100 5411.685077 5115.048256 5500.985916
1 5.7 500 110 4425.339734 4169.893681 4483.595803
2 10.0 367 110 5698.595376 5369.652565 5773.612841
3 11.1 1800 95 30820.717985 29180.106606 31384.785443
4 2.8 960 105 4165.270216 3930.726187 4226.877893
5 4.7 800 120 5860.057879 5506.509637 5919.496692
6 10.4 103 111 1663.960420 1567.455541 1685.339848
7 20.1 1950 115 60976.735053 57375.300546 61685.075902
Run Code Online (Sandbox Code Playgroud)
第一步是分组factors_df依据option。只是为了展示它的样子:
In [6]: groups.apply(print)
category pct option a b ... d e f g h
0 A 58 opt_1 0.000011 0.23521 ... 0.39458 0.00817 0.24566 0.0010 0.00
3 B 22 opt_1 0.002452 0.48327 ... 0.92852 0.00871 0.29568 0.0009 0.02
6 C 17 opt_1 0.082583 0.39493 ... 0.82714 0.00918 0.28572 0.0012 0.00
9 D 3 opt_1 0.018327 0.32342 ... 0.92752 0.00988 0.21958 0.0016 0.00
[4 rows x 11 columns]
category pct option a b ... d e f g h
1 A 58 opt_2 0.000011 0.23521 ... 0.39458 0.00467 0.24566 0.0010 0.00
4 B 22 opt_2 0.002899 0.49327 ... 0.92852 0.00871 0.30468 0.0009 0.02
7 C 17 opt_2 0.072587 0.35493 ... 0.82723 0.00912 0.29572 0.0018 0.00
10 D 3 opt_2 0.014427 0.32342 ... 0.92752 0.00968 0.22558 0.0026 0.00
[4 rows x 11 columns]
category pct option a b ... d e f g h
2 A 58 opt_3 0.000011 0.23521 ... 0.39458 0.00467 0.24566 0.0010 0.00
5 B 22 opt_3 0.002452 0.48327 ... 0.92852 0.00771 0.29568 0.0119 0.01
8 C 17 opt_3 0.082583 0.39493 ... 0.82714 0.00962 0.28572 0.0012 0.01
11 D 3 opt_3 0.018327 0.32342 ... 0.94452 0.00988 0.21258 0.0016 0.00
Run Code Online (Sandbox Code Playgroud)
请注意,我将其重命名category %为pct. 这不是必需的,但可以使访问formula()函数中的该列更加清晰(g.pctvs g["category %"])。
下一步是以接受一组作为参数的formula()方式来实现:factors_df
def formula(g, *, l, N_cars, v):
x = (1 - g.h) * (g.a * v*v + g.b*v + g.c + g.d/v) / (g.e * v*v + g.f*v + g.g)
return N_cars * l * (x * g.pct / 100).sum()
Run Code Online (Sandbox Code Playgroud)
在函数签名中,g是一组 from factors_df,然后是仅关键字参数l、N_cars和,它们一次v来自一行。input_df
formula()上面显示的三组中的每一组将一次完整地输入到该函数中。例如,在一次调用 期间formula(),g参数将保存所有这些数据:
category pct option a b ... d e f g h
0 A 58 opt_1 0.000011 0.23521 ... 0.39458 0.00817 0.24566 0.0010 0.00
3 B 22 opt_1 0.002452 0.48327 ... 0.92852 0.00871 0.29568 0.0009 0.02
6 C 17 opt_1 0.082583 0.39493 ... 0.82714 0.00918 0.28572 0.0012 0.00
9 D 3 opt_1 0.018327 0.32342 ... 0.92752 0.00988 0.21958 0.0016 0.00
Run Code Online (Sandbox Code Playgroud)
当公式使用类似 的内容时g.e,它会访问整个e列,并利用矢量化同时对整个列执行算术计算。当尘埃落定后,该系列中的每一项都x将Series是四个类别汽车的公式的结果。这是一个例子:
0 0.231242
3 0.619018
6 7.188941
9 1.792376
Run Code Online (Sandbox Code Playgroud)
注意到指数了吗?它们分别对应于类别A、B、C和D来自factors_df。
从那里,我们需要使用 的参数formula()调用 的每一行:input_dfaxispd.DataFrame.apply()
input_df.apply(lambda r: groups.apply(lambda g: formula(g, **r)), axis=1)
Run Code Online (Sandbox Code Playgroud)
是lambda r一个匿名函数对象,被传递给apply,应用于轴 1,这意味着一次r将是一行,例如:input_df
In [13]: input_df.apply(print, axis=1)
l 3.5
N_cars 1000.0
v 100.0
Name: 0, dtype: float64
.
.
.
Run Code Online (Sandbox Code Playgroud)
现在,在每个 row-wise 上apply,我们还在groupby 对象formula()上应用该函数。将行从关键字参数中解压出来,这有助于确保、和 的值不会在公式中被误用(无需担心它们传递到函数中的顺序)。groupslambda g: formula(g, **r)**rinput_dfvlN_carsformula()
| 归档时间: |
|
| 查看次数: |
727 次 |
| 最近记录: |