如何遍历 3-D 数组和多个数据帧?
How to loop through a 3-D array and multiple dataframes?
背景信息
multi_data
是一个 3d 数组,(10,5,5) 数组。对于这个例子 multi_data = np.arange(250).reshape(10,5,5)
10 个矩阵中的每一个都有 5X5 个状态 (A-E)。
每个矩阵都是按顺序排列的,并以年为单位表示时间,增量为 1。
从包含第 1 年矩阵值的矩阵 [0] 开始,直到第 10 年矩阵 [9]。
第 1 年 multi_data 的示例
multi_data[0]
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19],
[ 20, 21, 22, 23, 24]],
客户通常会在几年内进行购买(不是在注册时立即进行),例如,这位客户在第 3 年进行了一次购买。
因此,此客户的矩阵计算从第 3 年开始。
每个用户都有一个 current_state (A-E),我需要转换用户数据,以便我可以将其乘以矩阵。例如,用户 customer1
的当前状态为 B,因此金额是数组 customer1= np.array([0, 1000, 0, 0, 0])
中的第二个元素
数据框 1(客户)
cust_id|state|amount|year|
1 | B | 1000 | 3
2 | D | 500 | 2
multi_data = np.arange(250).reshape(10,5,5)
customer1= np.array([0, 1000, 0, 0, 0])
output = customer1
results = []
for arr in multi_data[3:4]: #customer purchases at year 3 hence I am multiplying customer1 by matrix at year 3
output = output@arr
results.append(output)
输出示例
results = [array([80000, 81000, 82000, 83000, 84000])]
然后我需要将结果乘以数据帧 2
dataframe_2
| year | lim %
| 1 | 0.19
| 2 | 0.11
| 3 | 0.02
| 10 | 0.23
所以我在第 3 年将结果乘以 lim %
。
dataframe2=dataframe2.loc[dataframe2['year'] == 3]
results=dataframe2['LimitPerc'].values * results
示例输出结果
[array([1600,1620,1640,1660,1680])]
然后我需要将这些结果乘以矩阵第 4 年,然后乘以 lim% 第 4 年,直到达到第 10 年。
像这样:
customer1= [array([1600,1620,1640,1660,1680])]
output = customer1
results = []
for arr in data[4:5]: #multiplying by year 4 matrix (multi_data)
output = output@arr
results.append(output)
dataframe2=dataframe2.loc[dataframe2['year'] == 4]
results=dataframe2['LimitPerc'].values * results
有没有更简单的手动操作更少的方法?我需要继续计算直到第 10 年,因为每个 customer.I 需要在每次计算后为每个客户保存结果。
附加信息:
我目前正在 运行 通过所有客户年份,如下所示,但我的问题是我有很多 vlookup 类型的计算,如 dataframe2
需要在每年之间为每个客户计算,我必须保存每次计算后每个客户的结果。
results_dict = {}
for _id, c, y in zip(cust_id ,cust_amt, year):
results = []
for m in multi_data[y:]:
c = c @ m
results.append(c)
results_dict[_id] = results
不幸的是,由于您需要所有中间结果,我认为不可能优化这么多,所以您需要循环。如果您不需要中间结果,您可以预先计算直到第 10 年的每一年的矩阵乘积。但是,它在这里没有用。
要将 look-ups 集成到您的循环中,您可以将所有数据帧放在一个列表中,然后使用 DataFrame 索引来查询值。此外,您可以将 state
转换为整数索引。请注意,您不需要创建 customer1
向量。由于只有一个位置是non-zero,所以可以直接把矩阵的相关行提取出来乘以amount
。
示例数据:
import pandas as pd
import numpy as np
customer_data = pd.DataFrame({"cust_id": [1, 2, 3, 4, 5, 6, 7, 8],
"state": ['B', 'E', 'D', 'A', 'B', 'E', 'C', 'A'],
"cust_amt": [1000,300, 500, 200, 400, 600, 200, 300],
"year":[3, 3, 4, 3, 4, 2, 2, 4],
"group":[10, 25, 30, 40, 55, 60, 70, 85]})
state_list = ['A','B','C','D','E']
# All lookups should be dataframes with the year and/or group and the value like these.
lookup1 = pd.DataFrame({'year': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'lim %': 0.1})
lookup2 = pd.concat([pd.DataFrame({'group':g, 'lookup_val': 0.1, 'year':range(1, 11)}
for g in customer_data['group'].unique())]).explode('year')
multi_data = np.arange(250).reshape(10,5,5)
预处理:
# Put all lookups in order of calculation in this list.
lookups = [lookup1, lookup2]
# Preprocessing.
# Transform the state to categorical code to use it as array index.
customer_data['state'] = pd.Categorical(customer_data['state'],
categories=state_list,
ordered=True).codes
# Set index on lookups.
for i in range(len(lookups)):
if 'group' in lookups[i].columns:
lookups[i] = lookups[i].set_index(['year', 'group'])
else:
lookups[i] = lookups[i].set_index(['year'])
计算结果:
results = {}
for customer, state, amount, start, group in customer_data.itertuples(name=None, index=False):
for year in range(start, len(multi_data)+1):
if year == start:
results[customer] = [[amount * multi_data[year-1, state, :]]]
else:
results[customer].append([results[customer][-1][-1] @ multi_data[year-1]])
for lookup in lookups:
if isinstance(lookup.index, pd.MultiIndex):
value = lookup.loc[(year, group)].iat[0]
else:
value = lookup.loc[year].iat[0]
results[customer][-1].append(value * results[customer][-1][-1])
访问结果:
# Here are examples of how you obtain the results from the dictionary:
# Customer 1 at start year, first result.
results[1][0][0]
# Customer 1 at start year, second result (which would be after lookup1 here).
results[1][0][1]
# Customer 1 at start year, third result (which would be after lookup2 here).
results[1][0][2]
# Customer 1 at year start+1, first result.
results[1][1][0]
# ...
# Customer c at year start+y, result k+1.
results[c][y][k]
背景信息
multi_data
是一个 3d 数组,(10,5,5) 数组。对于这个例子 multi_data = np.arange(250).reshape(10,5,5)
10 个矩阵中的每一个都有 5X5 个状态 (A-E)。
每个矩阵都是按顺序排列的,并以年为单位表示时间,增量为 1。
从包含第 1 年矩阵值的矩阵 [0] 开始,直到第 10 年矩阵 [9]。
第 1 年 multi_data 的示例
multi_data[0]
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19],
[ 20, 21, 22, 23, 24]],
客户通常会在几年内进行购买(不是在注册时立即进行),例如,这位客户在第 3 年进行了一次购买。
因此,此客户的矩阵计算从第 3 年开始。
每个用户都有一个 current_state (A-E),我需要转换用户数据,以便我可以将其乘以矩阵。例如,用户 customer1
的当前状态为 B,因此金额是数组 customer1= np.array([0, 1000, 0, 0, 0])
数据框 1(客户)
cust_id|state|amount|year|
1 | B | 1000 | 3
2 | D | 500 | 2
multi_data = np.arange(250).reshape(10,5,5)
customer1= np.array([0, 1000, 0, 0, 0])
output = customer1
results = []
for arr in multi_data[3:4]: #customer purchases at year 3 hence I am multiplying customer1 by matrix at year 3
output = output@arr
results.append(output)
输出示例
results = [array([80000, 81000, 82000, 83000, 84000])]
然后我需要将结果乘以数据帧 2
dataframe_2
| year | lim %
| 1 | 0.19
| 2 | 0.11
| 3 | 0.02
| 10 | 0.23
所以我在第 3 年将结果乘以 lim %
。
dataframe2=dataframe2.loc[dataframe2['year'] == 3]
results=dataframe2['LimitPerc'].values * results
示例输出结果
[array([1600,1620,1640,1660,1680])]
然后我需要将这些结果乘以矩阵第 4 年,然后乘以 lim% 第 4 年,直到达到第 10 年。
像这样:
customer1= [array([1600,1620,1640,1660,1680])]
output = customer1
results = []
for arr in data[4:5]: #multiplying by year 4 matrix (multi_data)
output = output@arr
results.append(output)
dataframe2=dataframe2.loc[dataframe2['year'] == 4]
results=dataframe2['LimitPerc'].values * results
有没有更简单的手动操作更少的方法?我需要继续计算直到第 10 年,因为每个 customer.I 需要在每次计算后为每个客户保存结果。
附加信息:
我目前正在 运行 通过所有客户年份,如下所示,但我的问题是我有很多 vlookup 类型的计算,如 dataframe2
需要在每年之间为每个客户计算,我必须保存每次计算后每个客户的结果。
results_dict = {}
for _id, c, y in zip(cust_id ,cust_amt, year):
results = []
for m in multi_data[y:]:
c = c @ m
results.append(c)
results_dict[_id] = results
不幸的是,由于您需要所有中间结果,我认为不可能优化这么多,所以您需要循环。如果您不需要中间结果,您可以预先计算直到第 10 年的每一年的矩阵乘积。但是,它在这里没有用。
要将 look-ups 集成到您的循环中,您可以将所有数据帧放在一个列表中,然后使用 DataFrame 索引来查询值。此外,您可以将 state
转换为整数索引。请注意,您不需要创建 customer1
向量。由于只有一个位置是non-zero,所以可以直接把矩阵的相关行提取出来乘以amount
。
示例数据:
import pandas as pd
import numpy as np
customer_data = pd.DataFrame({"cust_id": [1, 2, 3, 4, 5, 6, 7, 8],
"state": ['B', 'E', 'D', 'A', 'B', 'E', 'C', 'A'],
"cust_amt": [1000,300, 500, 200, 400, 600, 200, 300],
"year":[3, 3, 4, 3, 4, 2, 2, 4],
"group":[10, 25, 30, 40, 55, 60, 70, 85]})
state_list = ['A','B','C','D','E']
# All lookups should be dataframes with the year and/or group and the value like these.
lookup1 = pd.DataFrame({'year': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'lim %': 0.1})
lookup2 = pd.concat([pd.DataFrame({'group':g, 'lookup_val': 0.1, 'year':range(1, 11)}
for g in customer_data['group'].unique())]).explode('year')
multi_data = np.arange(250).reshape(10,5,5)
预处理:
# Put all lookups in order of calculation in this list.
lookups = [lookup1, lookup2]
# Preprocessing.
# Transform the state to categorical code to use it as array index.
customer_data['state'] = pd.Categorical(customer_data['state'],
categories=state_list,
ordered=True).codes
# Set index on lookups.
for i in range(len(lookups)):
if 'group' in lookups[i].columns:
lookups[i] = lookups[i].set_index(['year', 'group'])
else:
lookups[i] = lookups[i].set_index(['year'])
计算结果:
results = {}
for customer, state, amount, start, group in customer_data.itertuples(name=None, index=False):
for year in range(start, len(multi_data)+1):
if year == start:
results[customer] = [[amount * multi_data[year-1, state, :]]]
else:
results[customer].append([results[customer][-1][-1] @ multi_data[year-1]])
for lookup in lookups:
if isinstance(lookup.index, pd.MultiIndex):
value = lookup.loc[(year, group)].iat[0]
else:
value = lookup.loc[year].iat[0]
results[customer][-1].append(value * results[customer][-1][-1])
访问结果:
# Here are examples of how you obtain the results from the dictionary:
# Customer 1 at start year, first result.
results[1][0][0]
# Customer 1 at start year, second result (which would be after lookup1 here).
results[1][0][1]
# Customer 1 at start year, third result (which would be after lookup2 here).
results[1][0][2]
# Customer 1 at year start+1, first result.
results[1][1][0]
# ...
# Customer c at year start+y, result k+1.
results[c][y][k]