【问题标题】:python pandas ExcelWriter issue while formatting cells as textpython pandas ExcelWriter问题,同时将单元格格式化为文本
【发布时间】:2022-01-24 14:21:28
【问题描述】:

我需要为从 pandas 数据框写入的 Excel 工作表列着色。

这是一个示例,我将给出并解释我面临的问题。

df=pd.DataFrame(columns=['A2','B18'],data=[[10,123415209123456789],[12,1223152012345678088],[10,1234152091234566666],[12,1223152012345678777]],dtype='object')
print(df)

   A2                  B18
0  10   123415209123456789
1  12  1223152012345678088
2  10  1234152091234566666
3  12  1223152012345678777

print(df.info)

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 2 columns):
#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
0   A2      4 non-null      object
1   B18     4 non-null      object
dtypes: object(2)
memory usage: 192.0+ bytes
None

我确实对颜色有一些复杂的格式要求,不仅要对齐数据,还要对齐标题。这就是我想使用 excelwriter 而不是 pandas styler 的原因。

但是,我遇到了文本格式问题

#Create a Pandas Excel writer using XlsxWriter as the engine.
writer = pd.ExcelWriter(dataFolder + 'tmp_12_test126.xlsx', engine='xlsxwriter')

# Convert the dataframe to an XlsxWriter Excel object.
df.to_excel(writer,sheet_name='Sheet1',index=False)

# Get the xlsxwriter workbook and worksheet objects.
workbook  = writer.book

col_format=[{},{'bg_color': 'cyan', 'num_format': '@'}]

# Start iterating through the columns and the rows to apply the format
for col in range(df.shape[1]):
    for row in range(df.shape[0]):
        if len(col_format[col]) > 0 :
           worksheet.write(row+1,col,df.iloc[row,col],workbook.add_format(col_format[col]))

# Finally write the file
writer.save()

但这会写入 B18 列将其转换为科学计数法并导致丢失最后 4 位值。

谁能帮助我做错了什么? 我通读并发现 'num_format': '@' 是强制单元格为文本格式所必需的。 但由于某种原因,它不起作用。

【问题讨论】:

  • 当我按照给定的方式尝试您的数据框和df.to_excel() 时,我得到了一个科学格式的数字。如果我在 Excel 中将其格式化为“数字”,最后几位数字将变为零。这是我所期望的,因为 Excel 将数字存储为双精度数,因此它会丢失精度。所以我不太明白这样的说法:“基本上,如果我使用没有 excelwriter 的 df.to_excel() 将这个 df 写入 excel,它会将数据正确地写入 B18 列的 18 字节文本并且不会丢失任何数字”为我得到不同的结果。您最初是在数据框中将数字创建为字符串吗?
  • 你是对的。我会修改qn。最初我从 pandas read_sql 获取 df,当我通过 df.To_excel 编写时,它工作正常。为了说明,我用对象数据手动创建了一个 df,这也有同样的问题。
  • 如果您想准确显示所有数字,则必须将其作为字符串而不是数字传递给 Excel。作为测试,尝试在 Excel 的单元格中输入数字,看看会发生什么:最后几位数字变为零。一旦你传递了数字,即使你改变了显示格式,你也会失去精度。
  • 是的,请记住这一点,我已将 pandas 数据框列转换为对象。因此,从技术上讲,pandas 将字段作为字符串传递给 excel。那么,为什么它仍然把它当作数字呢?

标签: python excel pandas pandas.excelwriter


【解决方案1】:

使用dtype=object 不会将数字转换为字符串。相反,它试图将每个值强制转换为最合适的 python 类型。如果您想要字符串而不是数字,您可以使用默认类型 dtype=str(强制所有列)或使用 astype() 为每列选择不同的类型:

import pandas as pd

df1=pd.DataFrame(columns=['A2','B18'],
                 data=[[10,123415209123456789],
                       [12,1223152012345678088],
                       [10,1234152091234566666],
                       [12,1223152012345678777]],
                 dtype=object)

print('df1 types:')
[print(idx,type(val[0]),type(val[1])) for idx,val in df1.iterrows()]

df2=pd.DataFrame(columns=['A2','B18'],
                 data=[[10,123415209123456789],
                       [12,1223152012345678088],
                       [10,1234152091234566666],
                       [12,1223152012345678777]],
                 dtype=str)

print('df2 types:')
[print(idx,type(val[0]),type(val[1])) for idx,val in df2.iterrows()]

df3=pd.DataFrame(columns=['A2','B18'],
                 data=[[10,123415209123456789],
                       [12,1223152012345678088],
                       [10,1234152091234566666],
                       [12,1223152012345678777]]).astype({'A2': int, 'B18':str})

print('df3 types:')
[print(idx,type(val[0]),type(val[1])) for idx,val in df3.iterrows()]

输出:

df1 types:
0 <class 'int'> <class 'int'>
1 <class 'int'> <class 'int'>
2 <class 'int'> <class 'int'>
3 <class 'int'> <class 'int'>
df2 types:
0 <class 'str'> <class 'str'>
1 <class 'str'> <class 'str'>
2 <class 'str'> <class 'str'>
3 <class 'str'> <class 'str'>
df3 types:
0 <class 'int'> <class 'str'>
1 <class 'int'> <class 'str'>
2 <class 'int'> <class 'str'>
3 <class 'int'> <class 'str'>

【讨论】:

  • 将数据帧转换为 str 就可以了。这对我来说是一个新知识。非常感谢。
猜你喜欢
  • 2019-08-30
  • 2012-11-02
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2017-10-24
  • 2017-02-16
  • 2019-11-26
  • 2023-03-13
相关资源
最近更新 更多