Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用令牌有效地替换字符串列表中的数字_Python_Pandas_Cython - Fatal编程技术网

Python 用令牌有效地替换字符串列表中的数字

Python 用令牌有效地替换字符串列表中的数字,python,pandas,cython,Python,Pandas,Cython,我有一些字符串列表,其中一些字符串是整数。我想找到一种方法,根据数字的长度,用令牌快速替换超过100的数字 ['foo', 'bar', '3333'] -> ['foo', 'bar', '99994'] 我将在长度约为100的列表上执行此操作数百万次。我提出的纯python方法如下所示: def quash_large_numbers(tokens, threshold=100): def is_int(s): try: int(s)

我有一些字符串列表,其中一些字符串是整数。我想找到一种方法,根据数字的长度,用令牌快速替换超过100的数字

['foo', 'bar', '3333'] -> ['foo', 'bar', '99994']
我将在长度约为100的列表上执行此操作数百万次。我提出的纯python方法如下所示:

def quash_large_numbers(tokens, threshold=100):
    def is_int(s):
        try:
            int(s)
            return True
        except ValueError:
            return False

    BIG_NUMBER_TOKEN = '9999%d'
    tokens_no_high_nums = [BIG_NUMBER_TOKEN % len(t) if is_int(t) and int(t) > threshold else t
                           for t in tokens]
    return tokens_no_high_nums
我想看看是否可以通过
pandas
更快地完成这项工作,但对于小列表来说速度要慢得多,我可以想象从一系列到另一系列的来回转换所产生的所有开销

def pd_quash_large_numbers(tokens, threshold=100):
    BIG_NUMBER_TOKEN = 9999
    tokens_ser = pd.Series(tokens)
    int_tokens = pd.to_numeric(tokens_ser, errors='coerce')
    tokens_over_threshold = int_tokens > threshold
    str_lengths = tokens_ser[tokens_over_threshold].str.len().astype(str)

    tokens_ser[tokens_over_threshold] = BIG_NUMBER_TOKEN + str_lengths

    return tokens_ser.tolist()
有没有比这更有效的方法?可能通过cython?

新的更快的答案

v = np.array(['foo', 'bar', '3333'])
r = np.arange(v.size)
m = np.core.defchararray.isdigit(v)
g = v[m].astype(int) > 100
i = r[m][g]
t = np.array(['9999{}'.format(len(x)) for x in v[i].tolist()])
v = v.astype(t.dtype)
v[i] = t
v.tolist()

['foo', 'bar', '99994']
s = pd.Series(['foo', 'bar', '3333'])
s.loc[pd.to_numeric(s, 'coerce') > 100] = s.str.len().map('9999{}'.format)

s

0      foo
1      bar
2    99994
dtype: object
旧答案

v = np.array(['foo', 'bar', '3333'])
r = np.arange(v.size)
m = np.core.defchararray.isdigit(v)
g = v[m].astype(int) > 100
i = r[m][g]
t = np.array(['9999{}'.format(len(x)) for x in v[i].tolist()])
v = v.astype(t.dtype)
v[i] = t
v.tolist()

['foo', 'bar', '99994']
s = pd.Series(['foo', 'bar', '3333'])
s.loc[pd.to_numeric(s, 'coerce') > 100] = s.str.len().map('9999{}'.format)

s

0      foo
1      bar
2    99994
dtype: object

新的快速答案

v = np.array(['foo', 'bar', '3333'])
r = np.arange(v.size)
m = np.core.defchararray.isdigit(v)
g = v[m].astype(int) > 100
i = r[m][g]
t = np.array(['9999{}'.format(len(x)) for x in v[i].tolist()])
v = v.astype(t.dtype)
v[i] = t
v.tolist()

['foo', 'bar', '99994']
s = pd.Series(['foo', 'bar', '3333'])
s.loc[pd.to_numeric(s, 'coerce') > 100] = s.str.len().map('9999{}'.format)

s

0      foo
1      bar
2    99994
dtype: object
旧答案

v = np.array(['foo', 'bar', '3333'])
r = np.arange(v.size)
m = np.core.defchararray.isdigit(v)
g = v[m].astype(int) > 100
i = r[m][g]
t = np.array(['9999{}'.format(len(x)) for x in v[i].tolist()])
v = v.astype(t.dtype)
v[i] = t
v.tolist()

['foo', 'bar', '99994']
s = pd.Series(['foo', 'bar', '3333'])
s.loc[pd.to_numeric(s, 'coerce') > 100] = s.str.len().map('9999{}'.format)

s

0      foo
1      bar
2    99994
dtype: object


通过计算文本数字而不是进行任何转换,我获得了很好的加速效果。这项测试计划使它下降了近80%。它运行原始代码、我的文本检查代码和piRSquared的numpy代码。让最好的代码获胜

import time

# a thousand 100 item long lists to test
test_data = [['foo', 'bar', '3333'] * 33 for _ in range(1000)]

def quash_large_numbers(tokens, threshold=100):
    def is_int(s):
        try:
            int(s)
            return True
        except ValueError:
            return False

    BIG_NUMBER_TOKEN = '9999%d'
    tokens_no_high_nums = [BIG_NUMBER_TOKEN % len(t) if is_int(t) and int(t) > threshold else t
                           for t in tokens]
    return tokens_no_high_nums

start = time.time()
result = [quash_large_numbers(tokens, 100) for tokens in test_data]
print('original', time.time() - start)

def quash(somelist, digits):
    return [text if len(text) <= digits or not text.isdigit() else '9999' + str(len(text)) for text in somelist]

start = time.time()
result = [quash(item, 2) for item in test_data]
print('textual ', time.time() - start)

import numpy as np

def np_quash(somelist, threshold=100):
    v = np.array(somelist)
    r = np.arange(v.size)
    m = np.core.defchararray.isdigit(v)
    g = v[m].astype(int) > threshold
    i = r[m][g]
    t = np.array(['9999{}'.format(len(x)) for x in v[i].tolist()])
    v = v.astype(t.dtype)
    v[i] = t
    return v.tolist()

start = time.time()
result = [np_quash(item, 100) for item in test_data]
print('numpy   ', time.time() - start)

通过计算文本数字而不是进行任何转换,我获得了很好的加速效果。这项测试计划使它下降了近80%。它运行原始代码、我的文本检查代码和piRSquared的numpy代码。让最好的代码获胜

import time

# a thousand 100 item long lists to test
test_data = [['foo', 'bar', '3333'] * 33 for _ in range(1000)]

def quash_large_numbers(tokens, threshold=100):
    def is_int(s):
        try:
            int(s)
            return True
        except ValueError:
            return False

    BIG_NUMBER_TOKEN = '9999%d'
    tokens_no_high_nums = [BIG_NUMBER_TOKEN % len(t) if is_int(t) and int(t) > threshold else t
                           for t in tokens]
    return tokens_no_high_nums

start = time.time()
result = [quash_large_numbers(tokens, 100) for tokens in test_data]
print('original', time.time() - start)

def quash(somelist, digits):
    return [text if len(text) <= digits or not text.isdigit() else '9999' + str(len(text)) for text in somelist]

start = time.time()
result = [quash(item, 2) for item in test_data]
print('textual ', time.time() - start)

import numpy as np

def np_quash(somelist, threshold=100):
    v = np.array(somelist)
    r = np.arange(v.size)
    m = np.core.defchararray.isdigit(v)
    g = v[m].astype(int) > threshold
    i = r[m][g]
    t = np.array(['9999{}'.format(len(x)) for x in v[i].tolist()])
    v = v.astype(t.dtype)
    v[i] = t
    return v.tolist()

start = time.time()
result = [np_quash(item, 100) for item in test_data]
print('numpy   ', time.time() - start)


你的基本要求是什么?你说100。。。这真的是一个数字计数吗?可能根本不需要转换为整数。次要说明:不需要使用
is_int()
函数,因为您可以执行以下操作:
isinstance(t,int)
isinstance(t,long)
如果字符串可以转换为整数,则只需计算位数。不要认为
isinstance
可以像“3333”是一个字符串那样工作。我不希望从
Cython
得到太多帮助,因为它不能绕过两个基本的Python对象(及其方法)、列表和字符串。Cython没有自己的字符串代码;因此,它要么使用
c
字符串(笨拙),要么使用capi调用Python字符串方法。我认为/希望这只是一个简单的例子,因为使用
“9999”
作为大数字标记似乎是一个糟糕的想法。在同一数据上运行脚本两次将使100和9999999999之间的每个原始数字变成
“99995”
,运行脚本三次将使
100和
10^100000-1之间的每个数字变成
“99995”
。也许是像
“~10^”
这样的前缀你的基本要求是什么?你说100。。。这真的是一个数字计数吗?可能根本不需要转换为整数。次要说明:不需要使用
is_int()
函数,因为您可以执行以下操作:
isinstance(t,int)
isinstance(t,long)
如果字符串可以转换为整数,则只需计算位数。不要认为
isinstance
可以像“3333”是一个字符串那样工作。我不希望从
Cython
得到太多帮助,因为它不能绕过两个基本的Python对象(及其方法)、列表和字符串。Cython没有自己的字符串代码;因此,它要么使用
c
字符串(笨拙),要么使用capi调用Python字符串方法。我认为/希望这只是一个简单的例子,因为使用
“9999”
作为大数字标记似乎是一个糟糕的想法。在同一数据上运行脚本两次将使100和9999999999之间的每个原始数字变成
“99995”
,运行脚本三次将使
100和
10^100000-1之间的每个数字变成
“99995”
。也许是像
“~10^”
这样的前缀工作,但不是任何快速,因为我认为地图真的很慢。@Luke好的。。。我正在调查it@Luke我提供了另一个答案,但并不快,因为我认为地图真的很慢。@Luke好的。。。我正在调查it@Luke我提供了另一个答案哇。非常令人印象深刻!这很聪明,完全避免了数字转换,我注意到您包含了
re
,但没有使用它。在我的测试中,
re
(.050s)仍然比原始(.207s)/numpy(.066s)快,但比
isdigit
(.027s)慢。我在那里进行了
re
测试,但是
isdigit
更快。我将删除该工件。我怀疑
isdigit
访问C代码应该很快。哇。非常令人印象深刻!这很聪明,完全避免了数字转换,我注意到您包含了
re
,但没有使用它。在我的测试中,
re
(.050s)仍然比原始(.207s)/numpy(.066s)快,但比
isdigit
(.027s)慢。我在那里进行了
re
测试,但是
isdigit
更快。我将删除该工件。我怀疑
isdigit
访问C代码应该很快。