如何在 pandas df 中插入第二个 header 行以进行 csv 写入
How to insert a second header row in pandas df for csv write
我有一个非常大的 pandas df 我正在写到 csv。我需要添加第二个包含数据类型的 header 行。下面的代码有效,但在 CSV 中产生了第三个意外的空行:
#! /usr/bin/env python
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
# get count of header columns, add REAL for each one
types_header_for_insert = list(df.columns.values)
for idx, val in enumerate(types_header_for_insert):
types_header_for_insert[idx] = 'REAL'
# count number of index columns, then add STRING for each one
index_count = len(df.index.names)
for idx in range(0, index_count):
df.reset_index(level=0, inplace=True)
types_header_for_insert.insert(0, 'STRING')
# insert the new types column
df.columns = pd.MultiIndex.from_tuples(zip(df.columns, types_header_for_insert))
print df.columns.values
df.to_csv("./test.csv", index=False)
输出:
index,A,B
STRING,REAL,REAL
,,
0,1,2
1,3,4
我怎样才能去掉这个多余的空白行?它来自哪里?
我认为这是错误,请参阅 opened issue 6618。
也许可以帮助小技巧 - 在数据的第一行之前添加 types_header_for_insert
:
#! /usr/bin/env python
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
# get count of header columns, add REAL for each one
types_header_for_insert = list(df.columns.values)
for idx, val in enumerate(types_header_for_insert):
types_header_for_insert[idx] = 'REAL'
# count number of index columns, then add STRING for each one
index_count = len(df.index.names)
for idx in range(0, index_count):
df.reset_index(level=0, inplace=True)
types_header_for_insert.insert(0, 'STRING')
# insert the new types column
#df.columns = pd.MultiIndex.from_tuples(zip(df.columns, types_header_for_insert))
#set new value to dataframe
df.loc[-1] = types_header_for_insert
#sort index
df = df.sort_index()
print df
# index A B
#-1 STRING REAL REAL
# 0 0 1 2
# 1 1 3 4
print df.to_csv(index=False)
#index,A,B
#STRING,REAL,REAL
#0,1,2
#1,3,4
编辑
在大 df 中你可以使用 append
:
#empty df with column from df
df1 = pd.DataFrame(columns = df.columns)
#create series from types_header_for_insert
s = pd.Series(types_header_for_insert, index=df.columns)
print s
index STRING
A REAL
B REAL
dtype: object
df1 = df1.append(s, ignore_index=True).append(df, ignore_index=True)
print df1
index A B
0 STRING REAL REAL
1 0 1 2
2 1 3 4
print df1.to_csv(index=False)
index,A,B
STRING,REAL,REAL
0,1,2
1,3,4
在 Python 3 中,MultiIndex.from_tuples()
失败,类型 'zip' 的对象没有 len()。但是,将 zip 包装在 list()
中时没有空行。考虑在 Python 2:
中尝试
df.columns = pd.MultiIndex.from_tuples(list(zip(df.columns, types_header_for_insert)))
print df.columns.values
df.to_csv("./test.csv", index=False)
# index A B
# STRING REAL REAL
# 0 1 2
# 1 3 4
或者,使用列表理解来绕过 zip
:
data = [df.columns, types_header_for_insert]
newcolumns = [tuple(i[j] for i in data) for j in range(min(len(l) for l in data))]
df.columns = pd.MultiIndex.from_tuples(newcolumns)
print df.columns.values
df.to_csv("./test.csv", index=False)
# index A B
# STRING REAL REAL
# 0 1 2
# 1 3 4
我最后使用了一个变通方法 (a) 将原始 headers 写入 csv (b) 将 headers 替换为第二行 header 并附加整个df 到第一个文件:
# write the header to the file only
pd.DataFrame(data=[df.columns]).to_csv("outfile.csv", header=False, index=False)
# now replace header
types_header_for_insert = list(df.columns.values)
for idx, val in enumerate(df.columns.values):
if df[val].dtype == 'float64':
types_header_for_insert[idx] = 'REAL'
elif self.grouped[val].dtype == 'int64':
types_header_for_insert[idx] = 'INTEGER'
else:
types_header_for_insert[idx] = 'STRING'
df.columns = types_header_for_insert
# append the whole df with new header
df.to_csv("outfile.csv", mode="a", float_format='%.3f', index=False)
我有一个非常大的 pandas df 我正在写到 csv。我需要添加第二个包含数据类型的 header 行。下面的代码有效,但在 CSV 中产生了第三个意外的空行:
#! /usr/bin/env python
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
# get count of header columns, add REAL for each one
types_header_for_insert = list(df.columns.values)
for idx, val in enumerate(types_header_for_insert):
types_header_for_insert[idx] = 'REAL'
# count number of index columns, then add STRING for each one
index_count = len(df.index.names)
for idx in range(0, index_count):
df.reset_index(level=0, inplace=True)
types_header_for_insert.insert(0, 'STRING')
# insert the new types column
df.columns = pd.MultiIndex.from_tuples(zip(df.columns, types_header_for_insert))
print df.columns.values
df.to_csv("./test.csv", index=False)
输出:
index,A,B
STRING,REAL,REAL
,,
0,1,2
1,3,4
我怎样才能去掉这个多余的空白行?它来自哪里?
我认为这是错误,请参阅 opened issue 6618。
也许可以帮助小技巧 - 在数据的第一行之前添加 types_header_for_insert
:
#! /usr/bin/env python
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
# get count of header columns, add REAL for each one
types_header_for_insert = list(df.columns.values)
for idx, val in enumerate(types_header_for_insert):
types_header_for_insert[idx] = 'REAL'
# count number of index columns, then add STRING for each one
index_count = len(df.index.names)
for idx in range(0, index_count):
df.reset_index(level=0, inplace=True)
types_header_for_insert.insert(0, 'STRING')
# insert the new types column
#df.columns = pd.MultiIndex.from_tuples(zip(df.columns, types_header_for_insert))
#set new value to dataframe
df.loc[-1] = types_header_for_insert
#sort index
df = df.sort_index()
print df
# index A B
#-1 STRING REAL REAL
# 0 0 1 2
# 1 1 3 4
print df.to_csv(index=False)
#index,A,B
#STRING,REAL,REAL
#0,1,2
#1,3,4
编辑
在大 df 中你可以使用 append
:
#empty df with column from df
df1 = pd.DataFrame(columns = df.columns)
#create series from types_header_for_insert
s = pd.Series(types_header_for_insert, index=df.columns)
print s
index STRING
A REAL
B REAL
dtype: object
df1 = df1.append(s, ignore_index=True).append(df, ignore_index=True)
print df1
index A B
0 STRING REAL REAL
1 0 1 2
2 1 3 4
print df1.to_csv(index=False)
index,A,B
STRING,REAL,REAL
0,1,2
1,3,4
在 Python 3 中,MultiIndex.from_tuples()
失败,类型 'zip' 的对象没有 len()。但是,将 zip 包装在 list()
中时没有空行。考虑在 Python 2:
df.columns = pd.MultiIndex.from_tuples(list(zip(df.columns, types_header_for_insert)))
print df.columns.values
df.to_csv("./test.csv", index=False)
# index A B
# STRING REAL REAL
# 0 1 2
# 1 3 4
或者,使用列表理解来绕过 zip
:
data = [df.columns, types_header_for_insert]
newcolumns = [tuple(i[j] for i in data) for j in range(min(len(l) for l in data))]
df.columns = pd.MultiIndex.from_tuples(newcolumns)
print df.columns.values
df.to_csv("./test.csv", index=False)
# index A B
# STRING REAL REAL
# 0 1 2
# 1 3 4
我最后使用了一个变通方法 (a) 将原始 headers 写入 csv (b) 将 headers 替换为第二行 header 并附加整个df 到第一个文件:
# write the header to the file only
pd.DataFrame(data=[df.columns]).to_csv("outfile.csv", header=False, index=False)
# now replace header
types_header_for_insert = list(df.columns.values)
for idx, val in enumerate(df.columns.values):
if df[val].dtype == 'float64':
types_header_for_insert[idx] = 'REAL'
elif self.grouped[val].dtype == 'int64':
types_header_for_insert[idx] = 'INTEGER'
else:
types_header_for_insert[idx] = 'STRING'
df.columns = types_header_for_insert
# append the whole df with new header
df.to_csv("outfile.csv", mode="a", float_format='%.3f', index=False)