Что быстрее, сохранение в 2D-список или CSV для миллионов данных? - PullRequest
0 голосов
/ 14 ноября 2018

У меня более 20 миллионов строк данных, каждая строка содержит 60-200 элементов int.Мой нынешний метод использования:

with open("file.txt") as f:
    for block in reading_file(f):
        for line in block:                         
            a = line.split(" ")
            op_on_data(a)

, где reading_file() - это функция, которая занимает около 1000 строк одновременно.И op_on_data() - это функция, в которой я выполняю некоторые основные операции:

def op_on_data(a):
    if a[0] == "keyw":
        print 'keyw: ', a[0], a[1]
    else:
        # some_operations on arr[]
        for v in arr[splicing_here]:              
           if v > 100:
               # more_operations here
               two_d_list(particular_list_location).append(v)
        for e in arr[splicing_here]:
           if e < -100:
               two_d_list_2(particular_list_location).append(e)
    sys.stdout.flush()

И в конце я сохраняю two_d_list в кадре данных Pandas в ОДНОМ движении.Я не экономлю кусками.Приблизительно для 40000 строк тестового набора данных я получил начальное время ~10.5 s.Но когда я делаю весь набор данных, моя система падает после нескольких миллионов строк.Возможно, потому что список становится слишком большим.

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

Редактировать: я открыт для других опций, кроме списков и CSV.

1 Ответ

0 голосов
/ 14 ноября 2018

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

Если в любом случае вы перебираете строки, начните с этого

for line in open("file.txt"):  # open here is a generator (avoid using your own read functions)
    a = line.split(" ")
    op_on_data(a)

И для второго фрагмента кода, здесь есть больше комментариев к коду для кода ниже:

def op_on_data(a):
    if a[0] == "keyw":
        print 'keyw: ', a[0], a[1]    # Avoid printing when iterating million of lines !!!
    else:
        # some_operations on arr[]
        for v in arr[splicing_here]:  
           if v > 100:
               # more_operations here
               two_d_list(particular_list_location).append(v)
        for e in arr[splicing_here]:
           if e < -100:
               two_d_list_2(particular_list_location).append(e)
    sys.stdout.flush()

ОБЗОР КОДА ОТЗЫВОВ:

  1. Не итерируйте большие массивы просто с помощью цикла for, всегда используйте генераторы / итераторы, например ::

        from itertools import cycle
        my_iter_arr = cycle(arr)
        for v in my_iter_arr:
            # do something
    
  2. Попробуйте объединить 2 для циклов в 1. Я не вижу причины, по которой вы используете 2 для циклов, попробуйте:

    for v in my_iter_arr: 
         if v > 100:
             two_d_list(particular_list_location).append(v)
         elif v < -100:
             two_d_list_2(particular_list_location).append(v)
    
  3. И самое худшее - это добавление миллионов элементов в массив, хранящийся в ОЗУ, избегайте two_d_list(particular_list_location).append(v), я не уверен, насколько эффективен two_d_list! вместо этого попытайтесь увидеть, когда список достигает суммы элементов X, сбрасывает элементы в файл! и продолжайте добавлять в чистый список!

Попробуйте прочитать о Python Generators / Ленивая итерация

...