我有一个代码可以读取包含 3 列的 CSV 文件中的一列:区域、网外呼叫和流量。
示例数据:
Zone Offnet calls Traffic
zone0 0 0
zone1 421 30167
zone2 667 23172
zone3 12146 215033
zone4 7163 126514
zone5 5211 130045
zone6 1374 75357
zone7 3702 257846
zone8 1129 77677
zone9 2679 79331
我需要“网外通话”和“流量”来创建列表。例如,第 2 行将是 [421, 30167] 并从包含相同参数列表的列表中搜索最佳匹配/最接近的值。 看代码会更清楚:
tp_usp15 = [10, 200]
tp_usp23 = [15, 250]
tp_usp27 = [20, 300]
list_usp = [tp_usp15,tp_usp23, tp_usp27]
tp_bsnspls_s = [1,30]
tp_bsnspls_steel = [13,250]
tp_bsnspls_chrome = [18,350]
list_bsnspls = [tp_bsnspls_s,tp_bsnspls_steel,tp_bsnspls_chrome]
tp_bsnsrshn10 = [10,200]
tp_bsnsrshn15 = [15,300]
tp_bsnsrshn20 = [20,400]
list_bsnsrshn = [tp_bsnsrshn10,tp_bsnsrshn15,tp_bsnsrshn20]
common_list = list_usp + list_bsnspls + list_bsnsrshn
例如,从代码中提供的这个列表中,第 2 行 = [421, 30167] 的最接近值/最佳匹配是 [20, 400] = tp_bsnsrshn20。我需要一个代码来对 CSV 文件中的所有值进行相同的操作。最接近的值/最佳匹配需要记录到下一列(应在“流量”列旁边创建一个名为“最佳匹配”的新列)。我有一个适用于输入的代码。 2 个用户输入创建一个列表,搜索是从列表列表中完成的。
client_traffic = int(input("Enter the expected monthly traffic: "))
client_offnet = int(input("Enter monthly offnet calls: "))
list_client = [client_payment, client_offnet]
from functools import partial
def distance_squared(x, y):
return (x[0] - y[0])**2 + (x[1] - y[1])**2
best_match_overall = min(common_list, key=partial(distance_squared, list_client))
name_best_match_overall = [k for k,v in locals().items() if v == best_match_overall][0]
如何将此代码应用于整个 CSV 文件。顺便说一下,它还给出了值的名称。我想高级用户应该不难创建一些循环,该循环将按照我在上一个代码中提供的相同概念但针对整个文件工作。在这一点上,我真的很挣扎。提前致谢,伙计们!
答案 0 :(得分:1)
输入数据:
>>> df
Zone Offnet calls Traffic
0 zone0 0 0
1 zone1 421 30167
2 zone2 667 23172
3 zone3 12146 215033
4 zone4 7163 126514
5 zone5 5211 130045
6 zone6 1374 75357
7 zone7 3702 257846
8 zone8 1129 77677
9 zone9 2679 79331
将您的参考列表构建为数据框:
ref = {'tp_usp15': [10, 200],
'tp_usp23': [15, 250],
'tp_usp27': [20, 300],
'tp_bsnspls_s': [1, 30],
'tp_bsnspls_steel': [13, 250],
'tp_bsnspls_chrome': [18, 350],
'tp_bsnsrshn10': [10, 200],
'tp_bsnsrshn15': [15, 300],
'tp_bsnsrshn20': [20, 400]}
df1 = pd.DataFrame(ref, index=['crit1', 'crit2']).T.rename_axis('Name')
df1['Best Match'] = list(map(list, df1.values))
>>> df1
crit1 crit2 Best Match
Name
tp_usp15 10 200 [10, 200]
tp_usp23 15 250 [15, 250]
tp_usp27 20 300 [20, 300]
tp_bsnspls_s 1 30 [1, 30]
tp_bsnspls_steel 13 250 [13, 250]
tp_bsnspls_chrome 18 350 [18, 350]
tp_bsnsrshn10 10 200 [10, 200]
tp_bsnsrshn15 15 300 [15, 300]
tp_bsnsrshn20 20 400 [20, 400]
从 df
和 df1
创建笛卡尔积并计算平方距离:
cx = pd.merge(df.reset_index(), df1.reset_index(), how='cross')
x0, x1, y0, y1 = cx[['Offnet calls', 'Traffic', 'crit1', 'crit2']].values.T
cx['distance'] = (x0 - y0)**2 + (x1 - y1)**2
保留每个 df
行的最接近值:
cols = ['index', 'Zone', 'Offnet calls', 'Traffic', 'Best Match', 'Name']
out = cx.loc[cx.groupby('index')['distance'].idxmin(), cols] \
.set_index('index').rename_axis(None)
输出结果:
>>> out
Zone Offnet calls Traffic Best Match Name
0 zone0 0 0 [1, 30] tp_bsnspls_s
1 zone1 421 30167 [20, 400] tp_bsnsrshn20
2 zone2 667 23172 [20, 400] tp_bsnsrshn20
3 zone3 12146 215033 [20, 400] tp_bsnsrshn20
4 zone4 7163 126514 [20, 400] tp_bsnsrshn20
5 zone5 5211 130045 [20, 400] tp_bsnsrshn20
6 zone6 1374 75357 [20, 400] tp_bsnsrshn20
7 zone7 3702 257846 [20, 400] tp_bsnsrshn20
8 zone8 1129 77677 [20, 400] tp_bsnsrshn20
9 zone9 2679 79331 [20, 400] tp_bsnsrshn20