如何计算并向numpy数组元素添加字符串

2024-04-26 14:37:41 发布

您现在位置:Python中文网/ 问答频道 /正文

有这段代码,我正试图优化。 它使用列表理解和工作。在

series1 = np.asarray(range(10)).astype(float)
series2 = series1[::-1]

ntup = zip(series1,series2)
[['', 't:'+str(series2)][series1 > series2] for series1,series2 in ntup ]
 #['', '', '', '', '', 't:4.0', 't:3.0', 't:2.0', 't:1.0', 't:0.0']

正在尝试在此处使用np.where()。是否有numpy的解决方案。(不消耗系列)

^{pr2}$

结果是:

array(['', '', '', '', '', 't:[ 9.  8.  7.  6.  5.  4.  3.  2.  1.  0.]',
       't:[ 9.  8.  7.  6.  5.  4.  3.  2.  1.  0.]',
       't:[ 9.  8.  7.  6.  5.  4.  3.  2.  1.  0.]',
       't:[ 9.  8.  7.  6.  5.  4.  3.  2.  1.  0.]',
       't:[ 9.  8.  7.  6.  5.  4.  3.  2.  1.  0.]'], 
      dtype='|S43')

Tags: 代码in列表fornprangezipfloat
3条回答

我们可以使用基于

  • ^{}表示用有效字符串附加't:'的字符串,并且

  • ^{}根据条件语句选择并执行追加操作,或仅使用空字符串的默认值。

所以,我们会有这样的实现-

np.where(series1>series2,np.core.defchararray.add('t:',series2.astype(str)),'')

加油!

我们可以在基于series1>series2掩码的有效元素上使用np.core.defchararray.add附加np.core.defchararray.add来进一步提高性能,然后用默认的空字符串初始化一个数组,然后只将有效值赋给它。在

所以,修改后的版本应该是这样的-

^{pr2}$

运行时测试

矢量化版本作为函数:

def vectorized_app1(series1,series2):
    mask = series1>series2
    return np.where(mask,np.core.defchararray.add('t:',series2.astype(str)),'')

def vectorized_app2(series1,series2):
    mask = series1>series2
    out = np.full(series1.size,'',dtype='U34')
    out[mask] = np.core.defchararray.add('t:',series2[mask].astype(str))
    return out

在更大的数据集上计时-

In [283]: # Setup input arrays
     ...: series1 = np.asarray(range(10000)).astype(float)
     ...: series2 = series1[::-1]
     ...: 

In [284]: %timeit [['', 't:'+str(s2)][s1 > s2] for s1,s2 in zip(series1, series2)]
10 loops, best of 3: 32.1 ms per loop # OP/@hpaulj's soln

In [285]: %timeit vectorized_app1(series1,series2)
10 loops, best of 3: 20.5 ms per loop

In [286]: %timeit vectorized_app2(series1,series2)
100 loops, best of 3: 10.4 ms per loop

正如^{}所指出的那样,我们可能可以在追加之前先处理series2的数据类型。因此,我在那里使用U32来保持输出数据类型与strdtype相同,即np.core.defchararray.add调用中的series2.astype('U32')。矢量化方法的新计时是-

In [290]: %timeit vectorized_app1(series1,series2)
10 loops, best of 3: 20.1 ms per loop

In [291]: %timeit vectorized_app2(series1,series2)
100 loops, best of 3: 10.1 ms per loop

所以,有一些进一步的边际改善!在

你的列表理解只适用于列表,而不是真正需要使用数组。对于这样的操作,阵列可能不会带来任何速度优势。在

In [521]: series1=[float(i) for i in range(10)]
In [522]: series2=series1[::-1]
In [523]: [['', 't:'+str(s2)][s1 > s2] for s1,s2 in zip(series1, series2)]
Out[523]: ['', '', '', '', '', 't:4.0', 't:3.0', 't:2.0', 't:1.0', 't:0.0']

正如@Divaker所指出的,np.char.add函数将执行字符串操作。我的经验是,它们比列表操作稍微快一些。如果考虑到创建阵列的开销,它们可能会慢一些。在

=======

@Divakar显示的array版本

^{pr2}$

几个时间测试:

In [542]: timeit [['', 't:'+str(s2)][s1 > s2] for s1,s2 in zip(series1, series2)
     ...: ]
100000 loops, best of 3: 15.5 µs per loop

In [543]: timeit np.where(aseries1>aseries2, np.char.add('t:',aseries2.astype('U3')), '')
10000 loops, best of 3: 63 µs per loop

这对我有用。完全矢量化。在

import numpy as np
series1 = np.arange(10)
series2 = series1[::-1]
empties = np.repeat('', series1.shape[0])
ts = np.repeat('t:', series1.shape[0])
s2str = series2.astype(np.str)
m = np.vstack([empties, np.core.defchararray.add(ts, s2str)])
cmp = np.int64(series1 > series2)
idx = np.arange(m.shape[1])
res = m[cmp, idx]
print res 

相关问题 更多 >