Как улучшить скорость разбиения списка? - PullRequest
0 голосов
/ 11 июня 2018

Я просто хочу улучшить скорость разделения списка. Теперь у меня есть способ разделить список, но скорость не такая высокая, как я ожидал.

def split_list(lines):
        return [x for xs in lines for x in xs.split('-')]

import time

lst= []
for i in range(1000000):
    lst.append('320000-320000')

start=time.clock()
lst_new=split_list(lst)
end=time.clock()
print('time\n',str(end-start))

Например, Input:

lst
 ['320000-320000', '320000-320000']

Output:

lst_new
 ['320000', '320000', '320000', '320000']

Я не удовлетворен скоростью разделения, поскольку мои данные содержат много списков.

Но сейчасЯ не знаю, есть ли более эффективный способ сделать это.


Согласно совету, я пытаюсь описать весь свой вопрос более конкретно.

import pandas as pd

df = pd.DataFrame({ 'line':["320000-320000, 340000-320000, 320000-340000",
                            "380000-320000",
                            "380000-320000,380000-310000",
                            "370000-320000,370000-320000,320000-320000",
                            "320000-320000, 340000-320000, 320000-340000",
                            "380000-320000",
                            "380000-320000,380000-310000",
                            "370000-320000,370000-320000,320000-320000",
                            "320000-320000, 340000-320000, 320000-340000",
                            "380000-320000",
                            "380000-320000,380000-310000",
                            "370000-320000,370000-320000,320000-320000"], 'id':[1,2,3,4,5,6,7,8,9,10,11,12],})

def most_common(lst):
    return max(set(lst), key=lst.count)

def split_list(lines):
    return [x for xs in lines for x in xs.split('-')]

df['line']=df['line'].str.split(',')
col_ix=df['line'].index.values
df['line_start'] = pd.Series(0, index=df.index)
df['line_destination'] = pd.Series(0, index=df.index)

import time 
start=time.clock()

for ix in col_ix:
    col=df['line'][ix]
    col_split=split_list(col)
    even_col_split=col_split[0:][::2]
    even_col_split_most=most_common(even_col_split)
    df['line_start'][ix]=even_col_split_most

    odd_col_split=col_split[1:][::2]

    odd_col_split_most=most_common(odd_col_split)
    df['line_destination'][ix]=odd_col_split_most

end=time.clock()
print('time\n',str(end-start))

del df['line']
print('df\n',df)

Input:

df
 id                                         line
0    1  320000-320000, 340000-320000, 320000-340000
1    2                                380000-320000
2    3                  380000-320000,380000-310000
3    4    370000-320000,370000-320000,320000-320000
4    5  320000-320000, 340000-320000, 320000-340000
5    6                                380000-320000
6    7                  380000-320000,380000-310000
7    8    370000-320000,370000-320000,320000-320000
8    9  320000-320000, 340000-320000, 320000-340000
9   10                                380000-320000
10  11                  380000-320000,380000-310000
11  12    370000-320000,370000-320000,320000-320000

Output:

df
 id  line_start  line_destination
0    1     320000    320000
1    2     380000    320000
2    3     380000    320000
3    4     370000    320000
4    5     320000    320000
5    6     380000    320000
6    7     380000    320000
7    8     370000    320000
8    9     320000    320000
9   10     380000    320000
10  11     380000    320000
11  12     370000    320000

Можно считать число line (например, 320000-32000 представляет начальную точку и пункт назначения маршрута).

Expected: заставить код работать быстрее. (Я не могу выдержать скорость кода)

Ответы [ 3 ]

0 голосов
/ 11 июня 2018

Увеличение объема работы ниже уровня Python, по-видимому, обеспечивает небольшое ускорение:

In [7]: %timeit x = split_list(lst)
407 ms ± 876 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [8]: %timeit x = list(chain.from_iterable(map(methodcaller("split", "-"), lst
   ...: )))
374 ms ± 2.67 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

methodcaller создает функцию, которая вызывает функцию для вас:

methodcaller("split", "-")(x) == x.split("-")

chain.from_iterable создает один итератор, состоящий из элементов из группы итерируемых элементов:

list(chain.from_iterable([[1,2], [3,4]])) == [1,2,3,4]

map Пинг функции, возвращенной methodcaller в ваш список строк, создает итерацию списков, подходящих дляуплощение на from_iterable.Преимущество этого более функционального подхода заключается в том, что все задействованные функции реализованы в C и могут работать с данными в объектах Python, а не с байтовым кодом Python, который работает на Python.объекты.

0 голосов
/ 11 июня 2018
'-'.join(lst).split('-')

кажется немного быстрее:

>>> timeit("'-'.join(lst).split('-')", globals=globals(), number=10)
1.0838123590219766
>>> timeit("[x for xs in lst for x in xs.split('-')]", globals=globals(), number=10)
3.1370303670410067
0 голосов
/ 11 июня 2018

В зависимости от того, что вы хотите сделать со своим списком, использование генератора может быть немного быстрее.

Если вам нужно сохранить выходные данные, то решение для списка будет быстрее.

Если все, что вам нужно, это перебрать слов один раз, вы можете избавиться от некоторых накладных расходов, используя генератор.

def split_list_gen(lines):
    for line in lines:
        yield from line.split('-')

Benchmark

import time

lst = ['32000-32000'] * 10000000

start = time.clock()
for x in split_list(lst):
    pass
end = time.clock()
print('list time:', str(end - start))

start = time.clock()
for y in split_list_gen(lst):
    pass
end = time.clock()
print('generator time:', str(end - start))

Выходные данные

Генераторное решение работает примерно на 10% быстрее.

list time: 0.4568295369982612
generator time: 0.4020671741918084
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...