在python中,有没有更快的方法将字符串拆分为一个包含100万个元素的列表中的子列表

2024-03-28 21:20:02 发布

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

我正在尝试帮助我的朋友清理一个包含一百万个元素的订单列表数据帧。你知道吗

enter image description here

您可以看到product\u name列应该是一个列表,但它们是字符串类型。所以我想把它们分成子列表。你知道吗

这是我的密码:

order_ls = raw_df['product_name'].tolist()
cln_order_ls = list()
for i in order_ls:
    i = i.replace('[', '')
    i = i.replace(']', '')
    i = i.replace('\'', '')
    cln_order_ls.append(i)

new_cln_order_ls = list()
for i in cln_order_ls:
    new_cln_order_ls.append(i.split(', '))

但在“拆分”部分,需要花费大量时间来处理。我想知道有没有更快的办法来处理这个问题

~谢谢~


Tags: namein订单元素列表newfor朋友
3条回答

编辑

(我不喜欢上一个答案,它太混乱了,所以我重新排序,并进行了更系统的测试)。

长话短说:

对于速度,只需使用:

def str_to_list(s):
    return s[1:-1].replace('\'', '').split(', ')


df['product_name'].apply(str_to_list).to_list()

长话短说:

我们来分析一下你的代码:

order_ls = raw_df['product_name'].tolist()
cln_order_ls = list()
for i in order_ls:
    i = i.replace('[', '')
    i = i.replace(']', '')
    i = i.replace('\'', '')
    cln_order_ls.append(i)

new_cln_order_ls = list()
for i in cln_order_ls:
    new_cln_order_ls.append(i.split(', '))

您真正想做的是拥有一个函数,比如str_to_list(),它将您的输入str转换为list。你知道吗

出于某些原因,您可以分多个步骤来完成,但这确实不是必需的。到目前为止,您所拥有的可以重写为:

def str_to_list_OP(s):
    return s.replace('[', '').replace(']', '').replace('\'', '').split(', ')

如果可以假定[]始终是字符串的第一个和最后一个字符,则可以将其简化为:

def str_to_list(s):
    return s[1:-1].replace('\'', '').split(', ')

也应该更快。你知道吗

其他方法将使用正则表达式,例如:

def str_to_list_regex(s):
    regex = re.compile(r'[\[\]\']')
    return re.sub(regex, '', s).split(', ')

注意到目前为止所有的方法都使用split()。这是一个相当快的实现,接近C速度,几乎没有任何Python构造能打败它。你知道吗

所有这些方法都非常不安全,因为它们没有正确考虑转义,例如,对于以下有效的Python代码,上述所有方法都将失败:

['ciao', "pippo", 'foo, bar']

在这种情况下,更可靠的替代方案是:

  1. ast.literal_eval它适用于任何有效的Python代码
  2. json.loads这实际上需要有效的JSON字符串,因此它实际上不是一个选项。你知道吗

这些解决方案的速度比较如下:

benchmark1

正如你所见,安全是以速度为代价的。你知道吗

(这些图是使用these scripts生成的

def gen_input(n):
    return str([str(x) for x in range(n)])


def equal_output(a, b):
    return a == b


input_sizes = (5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000)  
funcs = str_to_list_OP, str_to_list, str_to_list_regex, ast.literal_eval 


runtimes, input_sizes, labels, results = benchmark(
    funcs, gen_input=gen_input, equal_output=equal_output,
    input_sizes=input_sizes)

现在让我们集中精力讨论循环。您所做的是显式循环,我们知道Python在这方面的速度通常不是很快。 但是,理解中的循环可以更快,因为它可以生成更优化的代码。 另一种方法是使用Pandas原语的向量化表达式,可以使用apply().str.链。你知道吗

获得以下计时,表明对于较小的输入,理解最快,尽管矢量化的解决方案(使用apply)赶上并最终超过理解:

benchmark2

使用了以下测试功能:

import pandas as pd


def str_to_list(s):
    return s[1:-1].replace('\'', '').split(', ')


def func_OP(df):
    order_ls = df['product_name'].tolist()
    cln_order_ls = list()
    for i in order_ls:
        i = i.replace('[', '')
        i = i.replace(']', '')
        i = i.replace('\'', '')
        cln_order_ls.append(i)
    new_cln_order_ls = list()
    for i in cln_order_ls:
        new_cln_order_ls.append(i.split(', '))
    return new_cln_order_ls


def func_QuangHoang(df):
    return df['product_name'].str[1:-1].str.replace('\'','').str.split(', ').to_list()


def func_apply_df(df):
    return df['product_name'].apply(str_to_list).to_list()


def func_compr(df):
    return [str_to_list(s) for s in df['product_name']]

具有以下测试代码:

def gen_input(n):
    return pd.DataFrame(
        columns=('order_id', 'product_name'),
        data=[[i, "['ciao', 'pippo', 'foo', 'bar', 'baz']"] for i in range(n)])


def equal_output(a, b):
    return a == b


input_sizes = (5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000)  
funcs = func_OP, func_QuangHoang, func_apply_df, func_compr 


runtimes, input_sizes, labels, results = benchmark(
    funcs, gen_input=gen_input, equal_output=equal_output,
    input_sizes=input_sizes)

再次使用与之前相同的base scripts。你知道吗

试试这个

import ast
raw_df['product_name'] = raw_df['product_name'].apply(lambda x : ast.literal_eval(x))

怎么样:

(df['product_name']
   .str[1:-1]
   .str.replace('\'','')
   .str.split(', ')
)

相关问题 更多 >