Создание Pandas Dataframe с генераторами вместо списков для повышения производительности - PullRequest
0 голосов
/ 28 апреля 2020

Этот вопрос относится к предыдущему вопросу, опубликованному здесь:

список пониманий с разрывом

Я хочу создать Pandas кадр данных следующим образом:

   0  1  2   3   4   5   6   7   8   9
0  4  5  6   9  10  16  21  23  25  27
1  5  7  7  11  11  17  24  24  26  56

И это код, который я написал до сих пор.

import pandas as pd
import timeit
from bisect import bisect_left

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]

# List comprehension with []
list3 = [list2[bisect_left(list2,i+1)] for i in list1]
print(list3)

# List comprehension with ()
list3_with_gen = (list2[bisect_left(list2,i+1)] for i in list1)
print(list3_with_gen)

# Timing the []
print(timeit.timeit('''

import timeit
from bisect import bisect_left

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]

list3 = [list2[bisect_left(list2,i+1)] for i in list1]

'''))

# Timing the ()
print(timeit.timeit('''

import timeit
from bisect import bisect_left

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]

list3 = (list2[bisect_left(list2,i+1)] for i in list1)

'''))

df = pd.DataFrame([list1, list3])
print(df)



# # original for loops
# list3 = []
# for i in list1:
#     for j in list2:
#         if j>i:
#             # print(i,j)
#             list3.append(j)
#             break
# # print(list1)
# # print(list3)

Вывод кода:

[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]
<generator object <genexpr> at 0x0000016618C46548>
3.8416419
1.3952507
   0  1  2   3   4   5   6   7   8   9
0  4  5  6   9  10  16  21  23  25  27
1  5  7  7  11  11  17  24  24  26  56

Что делает код?

  • Сравнивает время создания списка 3 с «Пониманием списка с помощью []» и list3_with_gen с «Пониманием списка с помощью ()».

  • Время «Понимания списка с помощью ()» примерно в 3 раза быстрее.

У меня есть некоторые проблемы с полным пониманием генераторов, и это не из-за отсутствия попыток. Моя цель состоит в том, чтобы создать фрейм данных как можно быстрее и эффективнее, потому что это небольшая выборка, и списки имеют большие размеры.

Есть ли способ, которым я могу создать этот фрейм данных, используя объект генератора list3_with_gen, так как это примерно в 3 раза быстрее для создания?

1 Ответ

0 голосов
/ 28 апреля 2020

В этом ответе не используется генератор, но его характеристики линейны по длинам входных списков 1 и 2. Для больших списков он должен превосходить наивное понимание и понимание с делением:

def merge(lst1, lst2):
    ret = []
    j = 0
    for elem in lst1:
        while(lst2[j] <= elem):
            j += 1
        ret.append(lst2[j])
    return ret

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]

print(merge(list1, list2))

печатает

[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]

Для получения запрошенного кадра данных:

import pandas as pd

def merge(lst1, lst2):
    ret = []
    j = 0
    for elem in lst1:
        while(lst2[j] <= elem):
            j += 1
        ret.append([elem, lst2[j]])
    return ret

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]

merged = merge(list1, list2)
df = pd.DataFrame(zip(*merged))
print(df)

печатает

   0  1  2   3   4   5   6   7   8   9
0  4  5  6   9  10  16  21  23  25  27
1  5  7  7  11  11  17  24  24  26  56
...