Pandas 和 XlsxWriter:如何更改格式并从数据框中的项目添加注释
Pandas and XlsxWriter: how to alter formatting and add comments from items in dataframe
我有一组数据框,经过大量修改后,它们对数据是否良好进行了评论和标记:
df = pd.DataFrame({'Name': ['a','a','b','b'],
'Measurements': ['temp','pressure','temp','pressure'],
'Values': [1, 2, -1, np.nan],
'Comment': ['','','Is negative', 'Is NaN'],
'IsBad':[False, False, True, True] })
measurements = df.reset_index().pivot(index='Name',columns='Measurements',values='Values')
comments = df.reset_index().pivot(index='Name',columns='Measurements',values='Comment')
bad_cells = df.reset_index().pivot(index='Name',columns='Measurements',values='IsBad')
我想做的是将其导出到一个 excel 文件,该文件的单元格格式为“IsBad”,并插入一条注释以解释单元格为何错误(忽略此示例开始在 A2...):
我一直在寻找几种不同的方法来做到这一点,但我被卡住了,我可以为每个旋转数据框创建一个带有新 sheet 的 excel 文件,但我不能'似乎无法使用其他 sheet 作为输入来创建评论。 XlsxWriter 似乎也不太擅长在循环中创建 excel 文件,在循环中我可以根据“df”对象中的行定义每个单元格。
有什么想法吗?
我最终得到了这个:
import pandas as pd
import xlsxwriter
df = pd.DataFrame({'Name': ['a','a','b','b'],
'Measurements': ['temp','pressure','temp','pressure'],
'Values': [1, 2, -1, -999],
'Comment': ['','','Is negative', 'Is NaN'],
'IsBad':[False, False, True, True] })
measurements = df.reset_index().pivot(index='Name',columns='Measurements',values='Values')
comments = df.reset_index().pivot(index='Name',columns='Measurements',values='Comment')
bad_cells = df.reset_index().pivot(index='Name',columns='Measurements',values='IsBad')
wb = xlsxwriter.Workbook('measurements.xlsx')
ws = wb.add_worksheet()
bg = wb.add_format({'bg_color': 'yellow'})
ws.write('A1', 'Name')
ws.write('B1', 'pressure')
ws.write('C1', 'temp')
i = 2
for key, row in measurements.iterrows():
ws.write('A' + str(i), key)
ws.write('B' + str(i), row[0])
ws.write('C' + str(i), row[1])
if bad_cells['pressure'].index.get_loc(key):
ws.write('B' + str(i), row[0], bg)
ws.write_comment('B' + str(i), comments['pressure'][i - 2])
if bad_cells['temp'].index.get_loc(key):
ws.write('C' + str(i), row[1], bg)
ws.write_comment('C' + str(i), comments['temp'][i - 2])
i += 1
wb.close()
我不得不将 np.nan
更改为 -999
,因为无法在 excel 中写入 NaN
值。
无论如何,您可以尝试其他替换:
xlsxwriter docs
Alex Montano 的回答很好,但由于在列 names/indexes 上进行了一些硬编码,因此在我的真实数据上效果不佳。我在这里发布了更通用的解决方案(基于他的工作)。我还从另一个 Whosebug 问题中引入了一个函数,它允许超过 26 列的表具有 AA、AB、AC...列:
import pandas as pd
import xlsxwriter
df = pd.DataFrame({'Name': ['a','a','b','b'],
'Measurements': ['temp','pressure','temp','pressure'],
'Values': [1, 2, -1, -999],
'Comment': ['','','Is negative', 'Is NaN'],
'IsBad':[False, False, True, True] })
measurements = df.reset_index().pivot(index='Name',columns='Measurements',values='Values')
comments = df.reset_index().pivot(index='Name',columns='Measurements',values='Comment')
bad_cells = df.reset_index().pivot(index='Name',columns='Measurements',values='IsBad')
#
def excel_cols():
n = 1
while True:
yield from (''.join(group) for group in itertools.product(string.ascii_uppercase, repeat=n))
n += 1
wb = xlsxwriter.Workbook('my_file.xlsx',{'strings_to_numbers': True})
ws = wb.add_worksheet('QC')
bad_format = wb.add_format({'bg_color': 'yellow'})
# Write column names, reset index so that they're just another column
xl_df = measurements.reset_index().astype(object).replace(np.nan, '')
column_index = list(itertools.islice(excel_cols(), len(xl_df.columns)))
# Create cell index values in Excel format ...X,Y,Z,AA,AB... etc
for column_ix, column in zip(column_index, xl_df.columns):
ws.write(column_ix + '1', column)
i = 2
for key, row in xl_df.iterrows():
for column_ix, column in zip(column_index, row.index):
this_index = column_ix + str(i)
cell_value = row[column]
this_cell_is_bad = bad_cells.reset_index()[column].iloc[key]
this_comment = comments.reset_index()[column].iloc[key]
if this_cell_is_bad == True:
ws.write(this_index, cell_value, bad_format)
ws.write_comment(this_index, this_comment)
else:
ws.write(this_index, cell_value)
i += 1
wb.close()
我有一组数据框,经过大量修改后,它们对数据是否良好进行了评论和标记:
df = pd.DataFrame({'Name': ['a','a','b','b'],
'Measurements': ['temp','pressure','temp','pressure'],
'Values': [1, 2, -1, np.nan],
'Comment': ['','','Is negative', 'Is NaN'],
'IsBad':[False, False, True, True] })
measurements = df.reset_index().pivot(index='Name',columns='Measurements',values='Values')
comments = df.reset_index().pivot(index='Name',columns='Measurements',values='Comment')
bad_cells = df.reset_index().pivot(index='Name',columns='Measurements',values='IsBad')
我想做的是将其导出到一个 excel 文件,该文件的单元格格式为“IsBad”,并插入一条注释以解释单元格为何错误(忽略此示例开始在 A2...):
我一直在寻找几种不同的方法来做到这一点,但我被卡住了,我可以为每个旋转数据框创建一个带有新 sheet 的 excel 文件,但我不能'似乎无法使用其他 sheet 作为输入来创建评论。 XlsxWriter 似乎也不太擅长在循环中创建 excel 文件,在循环中我可以根据“df”对象中的行定义每个单元格。
有什么想法吗?
我最终得到了这个:
import pandas as pd
import xlsxwriter
df = pd.DataFrame({'Name': ['a','a','b','b'],
'Measurements': ['temp','pressure','temp','pressure'],
'Values': [1, 2, -1, -999],
'Comment': ['','','Is negative', 'Is NaN'],
'IsBad':[False, False, True, True] })
measurements = df.reset_index().pivot(index='Name',columns='Measurements',values='Values')
comments = df.reset_index().pivot(index='Name',columns='Measurements',values='Comment')
bad_cells = df.reset_index().pivot(index='Name',columns='Measurements',values='IsBad')
wb = xlsxwriter.Workbook('measurements.xlsx')
ws = wb.add_worksheet()
bg = wb.add_format({'bg_color': 'yellow'})
ws.write('A1', 'Name')
ws.write('B1', 'pressure')
ws.write('C1', 'temp')
i = 2
for key, row in measurements.iterrows():
ws.write('A' + str(i), key)
ws.write('B' + str(i), row[0])
ws.write('C' + str(i), row[1])
if bad_cells['pressure'].index.get_loc(key):
ws.write('B' + str(i), row[0], bg)
ws.write_comment('B' + str(i), comments['pressure'][i - 2])
if bad_cells['temp'].index.get_loc(key):
ws.write('C' + str(i), row[1], bg)
ws.write_comment('C' + str(i), comments['temp'][i - 2])
i += 1
wb.close()
我不得不将 np.nan
更改为 -999
,因为无法在 excel 中写入 NaN
值。
无论如何,您可以尝试其他替换:
xlsxwriter docs
Alex Montano 的回答很好,但由于在列 names/indexes 上进行了一些硬编码,因此在我的真实数据上效果不佳。我在这里发布了更通用的解决方案(基于他的工作)。我还从另一个 Whosebug 问题中引入了一个函数,它允许超过 26 列的表具有 AA、AB、AC...列:
import pandas as pd
import xlsxwriter
df = pd.DataFrame({'Name': ['a','a','b','b'],
'Measurements': ['temp','pressure','temp','pressure'],
'Values': [1, 2, -1, -999],
'Comment': ['','','Is negative', 'Is NaN'],
'IsBad':[False, False, True, True] })
measurements = df.reset_index().pivot(index='Name',columns='Measurements',values='Values')
comments = df.reset_index().pivot(index='Name',columns='Measurements',values='Comment')
bad_cells = df.reset_index().pivot(index='Name',columns='Measurements',values='IsBad')
#
def excel_cols():
n = 1
while True:
yield from (''.join(group) for group in itertools.product(string.ascii_uppercase, repeat=n))
n += 1
wb = xlsxwriter.Workbook('my_file.xlsx',{'strings_to_numbers': True})
ws = wb.add_worksheet('QC')
bad_format = wb.add_format({'bg_color': 'yellow'})
# Write column names, reset index so that they're just another column
xl_df = measurements.reset_index().astype(object).replace(np.nan, '')
column_index = list(itertools.islice(excel_cols(), len(xl_df.columns)))
# Create cell index values in Excel format ...X,Y,Z,AA,AB... etc
for column_ix, column in zip(column_index, xl_df.columns):
ws.write(column_ix + '1', column)
i = 2
for key, row in xl_df.iterrows():
for column_ix, column in zip(column_index, row.index):
this_index = column_ix + str(i)
cell_value = row[column]
this_cell_is_bad = bad_cells.reset_index()[column].iloc[key]
this_comment = comments.reset_index()[column].iloc[key]
if this_cell_is_bad == True:
ws.write(this_index, cell_value, bad_format)
ws.write_comment(this_index, this_comment)
else:
ws.write(this_index, cell_value)
i += 1
wb.close()