用pandas编写单个CSV标头

时间:2018-01-01 21:02:53

标签: python pandas csv dataframe header

我将数据解析为列表并使用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 ,但是对于我的写入文件不起作用。

无论计数器仅为True一次,都会反复写入标题。当我在计数器为True时交换header = False,那么它永远不会写入标题。

我认为这是因为df以某种方式连接到标题的连接,但除此之外我无法弄清楚逻辑错误。

是否还有另一种方法我也可以只对同一个CSV文件写一次标题?

3 个答案:

答案 0 :(得分:4)

如果不看其余的代码,很难说出可能出现的问题。我开发了一些有效的测试数据和逻辑;你可以根据自己的需要进行调整。

请试试这个:

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)

答案 1 :(得分:0)

我发现了同样的问题。如果数据框已完成并且无需执行任何教程之外的任何工作,则熊猫 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')

如果文件不存在,我们将使用写入模式,并且标头等于标头列表。如果为假,并且文件存在,我们将使用append和header更改为0。

该函数接收一个简单的字典作为参数,就我而言,我使用了:

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

      }

多次使用ipython控制台中的函数形式会产生预期的结果:

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

让我知道是否有帮助。 编码愉快!

答案 2 :(得分:0)

如果您要使用索引遍历API调用以在csv文件中添加数据,只需在设置标头属性之前添加此检查。

<Field name="address">
 {({
    field, // { name, value, onChange, onBlur }
 }) => {
   values.address = values.mainAddress;
   return (
     <div>
        <input
           {...field}
           type="text"
           placeholder="Address"
         />
      </div>
    );
  }}
</Field>