我有大量数据:
>>> len(b)
6636849
>>> print(b)
[['60D19E9E-4E2C-11E2-AA9A-52540027E502' '100015361']
['60D19EB6-4E2C-11E2-AA9A-52540027E502' '100015385']
['60D19ECE-4E2C-11E2-AA9A-52540027E502' '100015409']
...,
['8CC90633-447E-11E6-B010-005056A76B49' '106636785']
['F8C74244-447E-11E6-B010-005056A76B49' '106636809']
['F8C7425C-447E-11E6-B010-005056A76B49' '106636833']]
我需要获取过滤后的数据集,即字符串中包含(或以“106”开头)的所有内容。类似下面的代码使用子字符串操作而不是数学运算:
>>> len(b[b[:,1] > '10660600'])
30850
答案 0 :(得分:1)
我认为numpy不适合这种类型的操作。你可以简单地使用基本的python操作。这是一些示例数据a
:
import random # for the test data
a = []
for i in range(10000):
a.append(["".join(random.sample('abcdefg',3)), "".join(random.sample('01234567890',8))])
answer = [i for i in a if i[1].find('106') != -1]
请注意,startswith
比find
快得多,因为find必须在所有位置查找匹配的子字符串。
为什么你需要首先使用如此庞大的列表/数组来解决这个问题并不太清楚,并且当首先不在列表中包含这些值时,可能会有更好的解决方案。
答案 1 :(得分:1)
这是一个简单的熊猫解决方案
import pandas as pd
df = pd.DataFrame(b, columns=['1st String', '2nd String'])
df_filtered = df[df['2nd String'].str.contains('106')]
这会给你
In [29]: df_filtered
Out[29]:
1st String 2nd String
3 8CC90633-447E-11E6-B010-005056A76B49 106636785
4 F8C74244-447E-11E6-B010-005056A76B49 106636809
5 F8C7425C-447E-11E6-B010-005056A76B49 106636833
更新:时间安排结果
使用Benjamin的列表a
作为测试样本:
In [20]: %timeit [i for i in a if i[1].find('106') != -1]
100 loops, best of 3: 2.2 ms per loop
In [21]: %timeit df[df['2nd String'].str.contains('106')]
100 loops, best of 3: 5.94 ms per loop
所以看起来Benjamin的答案实际上要快3倍。这让我感到惊讶,因为我的印象是the operation in pandas
is vectorized。此外,当a
长100倍时,速度比不会改变。
答案 2 :(得分:0)
查看np.char子模块中的函数:
data = [['60D19E9E-4E2C-11E2-AA9A-52540027E502', '100015361'],
['60D19EB6-4E2C-11E2-AA9A-52540027E502', '100015385'],
['60D19ECE-4E2C-11E2-AA9A-52540027E502', '100015409'],
['8CC90633-447E-11E6-B010-005056A76B49', '106636785'],
['F8C74244-447E-11E6-B010-005056A76B49', '106636809'],
['F8C7425C-447E-11E6-B010-005056A76B49', '106636833']]
data = np.array([r[1] for r in data], np.str)
idx = np.char.startswith(data, '106')
print(idx)