使用固定标头将pandas DataFrame附加到csv

时间:2018-11-03 12:17:09

标签: python pandas csv dataframe

我想将pandas DataFrames迭代地附加到一个csv文件中。通常这不是问题。但是,DataFrame可能不具有所有列。因此,只需将DataFrame追加到错误的列即可。

我从

开始
with open('test.csv', 'w') as output:
    writer = csv.writer(output, delimiter=',')
    writer.writerow(['a','b', 'c'])

然后例如我添加DataFrame df

    a   b   c
0   2   2.0 3
1   2   NaN 3

使用命令

df = pd.DataFrame([{'a':2, 'b':2, 'c':3}, {'a':2, 'c':3}])
df.to_csv('test.csv', index = False, header = False, mode = 'a') 

但是,我要附加的下一个DataFrame可能看起来像

    a   c
0   1   1
1   1   1

当我再次附加它时,我不愿意写标题,因为它已经存在。与以前一样(如预期的那样)无效:

df =pd.DataFrame([{'a':1, 'c':1}, {'a':1, 'c':1}])
df.to_csv('test.csv', index = False, header = False, mode = 'a')

产生

    a   b   c
0   2   2.0 3.0
1   2   NaN 3.0
2   1   1.0 NaN
3   1   1.0 NaN

当然我可以将现有的csv导入到DataFrame中,然后追加并覆盖旧文件:

file = pd.read_csv('test.csv')
df =pd.DataFrame([{'a':1, 'c':1}, {'a':1, 'c':1}])
file = file.append(df)
file.to_csv('test.csv', index = False, header = True)
pd.read_csv('test.csv')

这正是我想要的

    a   b   c
0   2   2.0 3
1   2   NaN 3
2   1   NaN 1
3   1   NaN 1

但是,当我多次重复该过程时,始终会读取整个csv文件并追加到大熊猫中并覆盖csv绝对对性能不好。我想将中间结果写入csv,因为如果我仅在pandas DataFrame中追加数据,然后发生错误,则所有聚合数据都会丢失。对我的问题有更好的解决方案吗?

我还尝试添加新的空列,但最后添加了它们,这无济于事,但可能有助于找到性能更好的解决方案。

def append_to_csv(df, file):
    if not os.path.exists(file):
        pd.to_csv(file, index = False, header = True)
    else:
        with open(file) as f:
            header = next(csv.reader(f))
        columns = df.columns
        for column in set(header) - set(columns):
            df[column] = np.nan
        df.to_csv(file, index = False, header = False, mode = 'a')

2 个答案:

答案 0 :(得分:2)

您总是可以像这样将空列附加到df

In [958]: df['b']=''

然后像这样重新构建df

In [959]: df = df[['a','b','c']]

In [960]: df
Out[960]: 
   a b  c
0  1    1
1  1    1

现在,将其写入csv。

In [961]: df.to_csv('test.csv', index = False, header = False, mode = 'a')

让我知道这是否有帮助。

答案 1 :(得分:0)

仅出于完整性考虑,我在此处使用Mayank Porwal的答案添加函数: 每当您要将DataFrame附加到具有指定标头的csv时。如果要允许新列(标题中不包含),则需要修改功能。

def append_to_csv(df, file):
    with open(file) as f:
        header = next(csv.reader(f))
    columns = df.columns
    for column in set(header) - set(columns):
        df[column] = ''
    df = df[header]
    df.to_csv(file, index = False, header = False, mode = 'a')