Я разбираю данные в списки и использую pandas для кадрирования и записи в файл CSV. Сначала мои данные помещаются в набор, где inv , name и date - все это списки с многочисленными записями. Затем я использую concat , чтобы объединить каждую итерацию наборов данных, которые я анализирую, в файл CSV следующим образом:

counter = True
data = {'Invention': inv, 'Inventor': name, 'Date': date}

if counter is True:
  df = pd.DataFrame(data)
  df = df[['Invetion', 'Inventor', 'Date']]

else:
  df = pd.concat([df, pd.DataFrame(data)])
  df = df[['Invention', 'Inventor', 'Date']]

  with open('./new.csv', 'a', encoding = utf-8) as f:
    if counter is True:
      df.to_csv(f, index = False, header = True)
    else:
      df.to_csv(f, index = False, header = False)

counter = False

Оператор counter = True находится вне моего цикла итерации для всех данных, которые я анализирую, поэтому он не перезаписывается каждый раз.

Это означает, что он проходит через мои данные только один раз , чтобы получить первый набор df , а затем объединить его. Проблема в том, что хотя счетчик равен только True в первом раунде и работает для моего первого if-statement для df, он не работает для моей записи в файл.

Что происходит, так это то, что заголовок записывается снова и снова - независимо от того, что counter имеет значение True только один раз. Когда я меняю значение header = False на значение True, он никогда не записывает заголовок.

Я думаю, это связано с тем, что df каким-то образом удерживает заголовок, но кроме этого я не могу понять логическую ошибку.

Может быть, есть другой способ записать заголовок один и только один раз в тот же файл CSV?

4
HelloToEarth 2 Янв 2018 в 00:02

2 ответа

Лучший ответ

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

Пожалуйста, попробуйте это:

import pandas as pd

early_inventions = ['wheel', 'fire', 'bronze']
later_inventions = ['automobile', 'computer', 'rocket']

early_names = ['a', 'b', 'c']
later_names = ['z', 'y', 'x']

early_dates = ['2000-01-01', '2001-10-01', '2002-03-10']
later_dates = ['2010-01-28', '2011-10-10', '2012-12-31']

early_data = {'Invention': early_inventions,
    'Inventor': early_names,
    'Date': early_dates}

later_data = {'Invention': later_inventions,
    'Inventor': later_names,
    'Date': later_dates}

datasets = [early_data, later_data]

columns = ['Invention', 'Inventor', 'Date']
header = True
for dataset in datasets:
    df = pd.DataFrame(dataset)
    df = df[columns]
    mode = 'w' if header else 'a'
    df.to_csv('./new.csv', encoding='utf-8', mode=mode, header=header, index=False)
    header = False

В качестве альтернативы вы можете объединить все данные в цикле и записать фрейм данных в конце:

df = pd.DataFrame(columns=columns)
for dataset in datasets:
    df = pd.concat([df, pd.DataFrame(dataset)])
    df = df[columns]
df.to_csv('./new.csv', encoding='utf-8', index=False)

Если ваш код не может соответствовать этому API, вы можете вообще отказаться от записи заголовка в to_csv. Вы можете определить, существует ли выходной файл, и сначала записать в него заголовок, если его нет:

import os

fn = './new.csv'
if not os.exists(fn):
    with open(fn, mode='w', encoding='utf-8') as f:
        f.write(','.join(columns) + '\n')
# now append the dataframe without a header
df.to_csv(fn, encoding='utf-8', mode='a', header=False, index=False)
6
Tom Lynch 2 Янв 2018 в 00:32

Я обнаружил ту же проблему. Pandas dataframe to csv отлично работает, если датафрейм завершен и нет необходимости делать что-либо, кроме любого учебника.

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

Чтобы решить эту проблему, рассмотрите следующую функцию:

def write_data_frame_to_csv_2(dict, path, header_list):
    df = pd.DataFrame.from_dict(data=dict, orient='index')
    filename = os.path.join(path, 'results_with_header.csv')
    if os.path.isfile(filename):
        mode = 'a'
        header = 0
    else:
        mode = 'w'
        header = header_list

    with open(filename, mode=mode) as f:
        df.to_csv(f, header=header, index_label='model')

Если файл не существует , мы используем режим записи , а заголовок совпадает со списком заголовков. Когда это ложь и файл существует , мы используем добавление, а заголовок изменен на 0.

Функция получает в качестве параметра простой словарь. В моем случае я использовал:

model = { 'model_name':{'acc':0.9,
                    'loss':0.3,
                    'tp':840,
                    'tn':450}

      }

Использование формы функции ipython console несколько раз дает ожидаемый результат:

write_data_frame_to_csv_2(model, './', header_list)

CSV создан:

model,acc,loss,tp,tn
model_name,0.9,0.3,840,450
model_name,0.9,0.3,840,450
model_name,0.9,0.3,840,450
model_name,0.9,0.3,840,450

Сообщите мне, если это поможет. Удачного кодирования!

0
LeninGF 23 Июл 2019 в 18:42