我要优化一个相当复杂的计算。我会利用pandas / numpy向量化,但不确定是否可以通过向量化解决此任务。目前,我正在使用pandas数据框,但使用for循环遍历该数据框。
任务说明:
查找表给出了映射。例如,old
“ 1”在new
“ 11”和“ 12”之间分配,分配比例为weight
。 60%的“ 1”传递给“ 11”,40%的传递给“ 12”。
另一个示例是将old
“ 2”重命名为new
“ 20”。因此,此处的分配比例为100%。
对于old
“ 3”(也分为{{1})“ 31”,“ 32”,“ 33”类似。
表new
中给出了“ 1”,“ 2”,“ 3”的实际值。在结果表df
中,new_df
的值需要通过乘以各个old
/比率来替换为new
。
我希望这种解释就足够了。下表将提供更多帮助。
权重(这是一个查找表)
weights
df(实际数据表/矩阵)
data = {'old':['1','1','2','3','3','3'], 'new':['11','12', '20','31','32','33'], 'Weight': [0.6, 0.4,1 ,0.2, 0.5, 0.3]}
weights = pd.DataFrame(data)
weights
old new Weight
0 1 11 0.6
1 1 12 0.4
2 2 20 1
3 3 31 0.2
4 3 32 0.5
5 3 33 0.3
new_df(结果数据帧)
data = {'A1':['1','1', '1', '2','2','2', '3','3'], 'A2':['1','2','3','1','2','3','1','2'], 'value': [50, 40, 30 ,10, 20, 70, 80, 90]}
df = pd.DataFrame(data)
df
A1 A2 value
0 1 1 50
1 1 2 40
2 1 3 30
3 2 1 10
4 2 2 20
5 2 3 70
6 3 1 80
7 3 2 90
下面是我现在正在使用的代码。但是,我给出的示例只是数据样本。有数千行,所以我需要以某种方式对其进行优化。
A1_new A2_new value_new | calculation (only for explanation)
0 11 11 18 | 50 * 0.6 * 0.6
1 12 12 8 | 50 * 0.4 * 0.4
2 11 12 12 | 50 * 0.6 * 0.4
3 12 11 12 | 50 * 0.6 * 0.4
4 11 20 24 | 40 * 1 * 0.6
5 12 20 16 | 40 * 1 * 0.4
6 11 31 3.6 | 30 * 0.6 * 0.2
7 11 32 9 | 30 * 0.6 * 0.5
8 11 33 5.4 | 30 * 0.6 * 0.3
9 12 31 2.4 | 30 * 0.4 * 0.2
10 12 32 6 | 30 * 0.4 * 0.5
11 12 33 3.6 | 30 * 0.4 * 0.3
12 31 11 9.6 | 80 * 0.2 * 0.6
13 32 11 24 | 80 * 0.5 * 0.6
14 33 11 14.4 | 80 * 0.3 * 0.6
15 31 12 6.4 | 80 * 0.2 * 0.4
16 32 12 16 | 80 * 0.5 * 0.4
17 33 12 9.6 | 80 * 0.3 * 0.4
18 31 20 16 | 80 * 0.2 * 1
19 32 20 40 | 80 * 0.5 * 1
20 33 20 24 | 80 * 0.3 * 1
答案 0 :(得分:4)
据我所知,您想根据其权重将(A1, A2)
的每种组合分成其所有可能的新组合(A1_new, A2_new)
和每种各自的新value
从您想要的输出中,当您有第一行时,我发现了一个小的不一致之处:
A1 A2 value
0 1 1 50
您是否只将以下两个结果行确实是真的?
A1_new A2_new value_new
0 11 11 30
1 12 12 20
而不是四行(例如所有可能的对)
A1_new A2_new value_new
0 11 11 18.0
1 11 12 12.0
2 12 11 12.0
3 12 12 8.0
如果确实如此,请在发生这种情况时添加有关确切规则的评论,我将编辑答案。
如上所述,以下解决方案使用所有可用的A1
和A2
替换对。通常的想法是使用两个A
列上的内部联接来“替换”列的所有旧值,然后根据联接的权重计算新值。
df = df\
.merge(weights, left_on="A1", right_on="old") \
.drop(columns=["A1", "old"]) \
.rename(columns={"new": "A1_new"}) \
.merge(weights, left_on="A2", right_on="old") \
.drop(columns=["A2", "old"]) \
.rename(columns={"new": "A2_new"})
df["value_new"] = df["value"] * df["Weight_x"] * df["Weight_y"]
df = df.drop(columns=["value", "Weight_x", "Weight_y"])
A1_new A2_new value_new
0 11 11 18.0
1 11 12 12.0
2 12 11 12.0
3 12 12 8.0
4 20 11 6.0
5 20 12 4.0
6 31 11 9.6
7 31 12 6.4
8 32 11 24.0
9 32 12 16.0
10 33 11 14.4
11 33 12 9.6
12 11 20 24.0
13 12 20 16.0
14 20 20 20.0
15 31 20 18.0
16 32 20 45.0
17 33 20 27.0
18 11 31 3.6
19 11 32 9.0
20 11 33 5.4
21 12 31 2.4
22 12 32 6.0
23 12 33 3.6
24 20 31 14.0
25 20 32 35.0
26 20 33 21.0