Python Pandas/numpy有助于矢量化数据帧之间的查找、计算和重新排序顺序
我正在尝试处理三个(csv)文件中的数据,如p、c、f:Python Pandas/numpy有助于矢量化数据帧之间的查找、计算和重新排序顺序,python,numpy,pandas,Python,Numpy,Pandas,我正在尝试处理三个(csv)文件中的数据,如p、c、f: 在p中,每行都有标签 在c中,每行都有p中对应行标签的分数(p与c匹配) 在f中,每行是一个标签和另一个分数 例如,分别加载到df_p、df_c和df_f中: >>> df_p p1 p2 p3 p4 p5 2614 104 104 102 102 102 3735 100 103 101 100 104 1450 100 102 100 102 102 &
- 在p中,每行都有标签
- 在c中,每行都有p中对应行标签的分数(p与c匹配)
- 在f中,每行是一个标签和另一个分数
>>> df_p
p1 p2 p3 p4 p5
2614 104 104 102 102 102
3735 100 103 101 100 104
1450 100 102 100 102 102
>>> df_c
c1 c2 c3 c4 c5
2614 0.338295 0.190882 0.157231 0.135776 0.177816
3735 0.097800 0.124296 0.268475 0.265111 0.244319
1450 0.160922 0.403703 0.122390 0.130612 0.182373
>>> df_f
c
100 0.183946
101 0.290311
102 0.192049
103 0.725704
104 0.143359
阿尔戈
例如,df\u c
中的第一个计算单元将是0.338295*0.143359
这是我的代码,虽然运行非常缓慢:
np_p = []
np_c = []
for i in range(len(df_p)):
## determine revised scores
# Step 1. Revise scores
r_conf = df_c.iloc[[i]].values[0] # scores for row
r_place_id = df_p.iloc[[i]].values[0] # labels for row
p_c = df_f.ix[r_place_id].c.values # class conf for labels
t_conf = r_conf*p_c # total score
# Reorder labels
# Step 2. reorder by revised score
c = np.sort(t_conf)[::-1]
c_sort = np.argsort(t_conf)[::-1]
# Step 3. reorder labels with revised score order
p_sort = df_p.iloc[[i]][df_p.columns[c_sort]].values
np_c.append(c)
np_p.append(p_sort)
理想情况下,我希望创建一个像df_p
和df_c
这样的数据帧,但要使用重新排序和修订的值(在np_p
和np_c
)
我有什么想法可以让这更快吗
谢谢 您可以使用将df\u p
中的值替换为df\u f
中的值:
In [124]: df_pf = df_p.replace(df_f['c']); df_pf
Out[124]:
p1 p2 p3 p4 p5
2614 0.143359 0.143359 0.192049 0.192049 0.192049
3735 0.183946 0.725704 0.290311 0.183946 0.143359
1450 0.183946 0.192049 0.183946 0.192049 0.192049
由于Pandas在两个数据帧相乘之前对齐索引,如果我们去掉
p
s和c
s,然后我们可以获得所需的产品
使用df_pf.mul(df_c)
:
使用指定了轴=1的np.argsort
可以获得每行列的正确顺序。然后可以使用np.argsort
返回的order
数组对df_c
和df_p
进行重新排序:
order = np.argsort(-df_c.values, axis=1)
nrows, ncols = df_c.shape
np_c = df_c.values[np.arange(nrows)[:,None], order]
np_p = df_p.values[np.arange(nrows)[:,None], order]
上面使用NumPy分别对每行中的值重新排序
屈服
[[ 0.04849763 0.03414938 0.03019606 0.02736465 0.02607565]
[ 0.0902021 0.07794125 0.04876611 0.03502533 0.01798992]
[ 0.07753076 0.03502455 0.02960096 0.0250839 0.02251315]]
[[104 102 102 104 102]
[103 101 100 104 100]
[102 102 100 102 100]]
或者,如果
df_p
和df_c
的列和行已经对齐,
然后,您可以通过使用NumPy而不是Pandas进行乘法来获得更快的速度:
def using_numpy(df_p, df_c, df_f):
# faster than using_pandas, but assumes `df_p` and `df_c` are already aligned
df_pf = df_p.replace(df_f['c'])
df_pf = df_pf.values
df_c = df_c.values
df_p = df_p.values
df_c = df_pf * df_c
order = np.argsort(-df_c, axis=1)
nrows, ncols = df_c.shape
np_c = df_c[np.arange(nrows)[:,None], order]
np_p = df_p[np.arange(nrows)[:,None], order]
return np_c, np_p
对于这些小数据帧,使用_numpy
比使用_pandas
稍微快一些。
如果数据帧更大,速度上的差异会更明显。
但是再次注意,使用_numpy的依赖于已经对齐的索引
In [138]: %timeit using_numpy(df_p, df_c, df_f)
1000 loops, best of 3: 1.15 ms per loop
In [139]: %timeit using_pandas(df_p, df_c, df_f)
1000 loops, best of 3: 1.62 ms per loop
试试这个:首先创建一个dict ofdf\u f
di = df_f['c'].to_dict()
{100: 0.183946,
101: 0.29031099999999999,
102: 0.192049,
103: 0.72570400000000002,
104: 0.14335899999999999}
然后将其映射到df_p:
df_p.replace(di)
# p1 p2 p3 p4 p5
# 2614 0.143359 0.143359 0.192049 0.192049 0.192049
# 3735 0.183946 0.725704 0.290311 0.183946 0.143359
# 1450 0.183946 0.192049 0.183946 0.192049 0.192049
然后进行乘法运算:
df_c2 =df_c.copy()
df_c2['c1'] = df_c['c1']* df_p['p1']
df_c2['c2'] = df_c['c2']* df_p['p2']
df_c2['c3'] = df_c['c3']* df_p['p3']
df_c2['c4'] = df_c['c4']* df_p['p4']
df_c2['c5'] = df_c['c5']* df_p['p5']
# c1 c2 c3 c4 c5
# 2614 0.048498 0.027365 0.030196 0.026076 0.034149
# 3735 0.017990 0.090202 0.077941 0.048766 0.035025
# 1450 0.029601 0.077531 0.022513 0.025084 0.035025
有五列可供使用。2.按递减分数对df_c的元素重新排序。@unutbu。你能解释np.argsort(-df_c,axis=1)吗?@Merlin:返回对数组排序的索引。例如,np.argsort([1,3,2])
返回数组([0,2,1])
,因为要按升序对[1,3,2]
进行排序,第0项首先出现,然后是第2项,然后是第1项np.argsort([[1,3,2],[20,30,10]],axis=1)
类似于行堆叠np.argsort([1,3,2])
和np.argsort([20,30,10])
。在np.argsort(-df_c,axis=1)
中使用减号对df_c
的每一行按降序进行argsort。@unutbu-非常有效、完整、直观!我不得不将数据帧分解成块以放入内存中,因为我的数据比上面的示例大得多,但在其他方面非常简洁和优雅,我学会了一些技巧。非常感谢。
di = df_f['c'].to_dict()
{100: 0.183946,
101: 0.29031099999999999,
102: 0.192049,
103: 0.72570400000000002,
104: 0.14335899999999999}
df_p.replace(di)
# p1 p2 p3 p4 p5
# 2614 0.143359 0.143359 0.192049 0.192049 0.192049
# 3735 0.183946 0.725704 0.290311 0.183946 0.143359
# 1450 0.183946 0.192049 0.183946 0.192049 0.192049
df_c2 =df_c.copy()
df_c2['c1'] = df_c['c1']* df_p['p1']
df_c2['c2'] = df_c['c2']* df_p['p2']
df_c2['c3'] = df_c['c3']* df_p['p3']
df_c2['c4'] = df_c['c4']* df_p['p4']
df_c2['c5'] = df_c['c5']* df_p['p5']
# c1 c2 c3 c4 c5
# 2614 0.048498 0.027365 0.030196 0.026076 0.034149
# 3735 0.017990 0.090202 0.077941 0.048766 0.035025
# 1450 0.029601 0.077531 0.022513 0.025084 0.035025