Как добавить строки в кадр данных pandas с разумной производительностью - PullRequest
0 голосов
/ 25 июня 2018

У меня есть пустой фрейм данных с примерно 120 столбцами, я хочу заполнить его данными из моего файла.

Я перебираю файл с 1,8 миллионами строк. (Строки не структурированы, я не могу загрузить их непосредственно в кадр данных)

Для каждой строки в файле я делаю следующее:

  • Извлечение нужных мне данных из текущей строки
  • Скопируйте последнюю строку во фрейме данных и добавьте ее в конец df = df.append(df.iloc[-1]). Копия является критической, большинство данных в предыдущей строке не будут изменены.
  • Измените несколько значений в последней строке в соответствии с данными, которые я извлек df.iloc[-1, df.columns.get_loc('column_name')] = some_extracted_value

Это очень медленно, я полагаю, ошибка в дополнении.

Каков правильный подход к ускорению вещей? предварительно распределить фрейм данных?

EDIT:

Прочитав ответы, я сделал следующее:

  • Я предварительно выделил фрейм данных (сохраняется как 10% времени)
  • Я заменил это: df = df.append(df.iloc[-1]) на это: df.iloc[i] = df.iloc[i-1] (i - текущая итерация в цикле). (Экономьте как 10% времени).
  • Сделал профилирование, хотя я удалил и добавляю, главная проблема - копирование предыдущей строки, что означает: df.iloc[i] = df.iloc[i-1] занимает около 95% времени.

Ответы [ 4 ]

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

Вы можете попробовать несколько мультипроцессоров, чтобы ускорить процесс

from multiprocessing.dummy import Pool as ThreadPool 
def YourCleaningFunction(line):
    for each line do the following 
    blablabla
    return(your formated lines with ,) # or use the kind of function jpp just provided

pool = ThreadPool(8) # your number of cores
lines = open('your_big_csv.csv').read().split('\n') # your csv as a list of lines
df = pool.map(YourCleaningFunction, lines)
df = pandas.DataFrame(df)
pool.close() 
pool.join()
0 голосов
/ 25 июня 2018

Где вы используете append, вы в конечном итоге копируете кадр данных, который неэффективен. Попробуйте все это снова, но избегайте этой строки:
df = df.append(df.iloc[-1])

Вы можете сделать что-то вроде этого, чтобы скопировать последнюю строку в новую строку (только если последняя строка содержит информацию, которую вы хотите в новой строке):
df.iloc[...calculate the next available index...] = df.iloc[-1]

Затем отредактируйте последнюю строку соответственно, как вы сделали
df.iloc[-1, df.columns.get_loc('column_name')] = some_extracted_value

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

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

Однако, чего вам, безусловно, следует избегать, это использовать pd.DataFrame.append внутри цикла.Это дороже по сравнению с list.append.

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

# initialize empty list
L = []

for line in my_binary_file:

    # extract components required from each line to a list of Python types
    line_vars = [line['var1'], line['var2'], line['var3']]

    # append to list of results
    L.append(line_vars)

# create dataframe from list of lists
df = pd.DataFrame(L, columns=['var1', 'var2', 'var3'])
0 голосов
/ 25 июня 2018

Самый быстрый способ - загрузить данные в фрейм напрямую с помощью pd.read_csv (). Попробуйте разделить логику для очистки неструктурированных и структурированных данных, а затем используйте pd.read_csv для загрузки фрейма данных.

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

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