如何使用 Pandas 在现有的 excel 文件中保存新工作表?

Posted

技术标签:

【中文标题】如何使用 Pandas 在现有的 excel 文件中保存新工作表?【英文标题】:How to save a new sheet in an existing excel file, using Pandas? 【发布时间】:2017-07-11 06:59:51 【问题描述】:

我想使用 excel 文件来存储用 python 详细说明的数据。我的问题是我无法将工作表添加到现有的 Excel 文件中。在这里,我建议使用示例代码来解决此问题

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

x1 = np.random.randn(100, 2)
df1 = pd.DataFrame(x1)

x2 = np.random.randn(100, 2)
df2 = pd.DataFrame(x2)

writer = pd.ExcelWriter(path, engine = 'xlsxwriter')
df1.to_excel(writer, sheet_name = 'x1')
df2.to_excel(writer, sheet_name = 'x2')
writer.save()
writer.close()

此代码将两个 DataFrame 保存到两个工作表中,分别命名为“x1”和“x2”。如果我创建两个新 DataFrame 并尝试使用相同的代码添加两个新工作表“x3”和“x4”,则原始数据会丢失。

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

x3 = np.random.randn(100, 2)
df3 = pd.DataFrame(x3)

x4 = np.random.randn(100, 2)
df4 = pd.DataFrame(x4)

writer = pd.ExcelWriter(path, engine = 'xlsxwriter')
df3.to_excel(writer, sheet_name = 'x3')
df4.to_excel(writer, sheet_name = 'x4')
writer.save()
writer.close()

我想要一个包含四张纸的 excel 文件:“x1”、“x2”、“x3”、“x4”。 我知道“xlsxwriter”不是唯一的“引擎”,还有“openpyxl”。我也看到已经有其他人写过关于这个问题的文章,但我仍然不明白该怎么做。

这里的代码取自link

import pandas
from openpyxl import load_workbook

book = load_workbook('Masterfile.xlsx')
writer = pandas.ExcelWriter('Masterfile.xlsx', engine='openpyxl') 
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)

data_filtered.to_excel(writer, "Main", cols=['Diff1', 'Diff2'])

writer.save()

他们说它有效,但很难弄清楚如何。我不明白在这种情况下“ws.title”、“ws”和“dict”是什么。

保存“x1”和“x2”的最佳方法是什么,然后关闭文件,再次打开并添加“x3”和“x4”?

【问题讨论】:

【参考方案1】:

在您分享的示例中,您将现有文件加载到book 并将writer.book 值设置为book。在writer.sheets = dict((ws.title, ws) for ws in book.worksheets) 行中,您以ws 的身份访问工作簿中的每个工作表。然后工作表标题为ws,因此您正在创建一个包含sheet_titles: sheet 键值对的字典。然后将此字典设置为 writer.sheets。 基本上这些步骤只是从'Masterfile.xlsx' 加载现有数据并用它们填充您的编写器。

现在假设您已经有一个文件,其中包含 x1x2 作为工作表。您可以使用示例代码加载文件,然后可以执行类似的操作来添加x3x4

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"
writer = pd.ExcelWriter(path, engine='openpyxl')
df3.to_excel(writer, 'x3', index=False)
df4.to_excel(writer, 'x4', index=False)
writer.save()

这应该可以满足您的需求。

【讨论】:

任何想法,为什么当我尝试这个时我得到:ValueError: No Excel writer 'Sales Leads Calculations.xlsx'? 这将擦除预先存在的工作表。【参考方案2】:

我强烈建议您直接与openpyxl since it now supports Pandas DataFrames 合作。

这使您可以专注于相关的 Excel 和 Pandas 代码。

【讨论】:

如果您可以添加更多类似于this的“熊猫”示例,那将非常有帮助 我自己对 Pandas 的工作并不多,所以我无法提供那么多示例,但欢迎改进文档。【参考方案3】:

谢谢。我相信一个完整的例子可能对任何有同样问题的人都有好处:

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

x1 = np.random.randn(100, 2)
df1 = pd.DataFrame(x1)

x2 = np.random.randn(100, 2)
df2 = pd.DataFrame(x2)

writer = pd.ExcelWriter(path, engine = 'xlsxwriter')
df1.to_excel(writer, sheet_name = 'x1')
df2.to_excel(writer, sheet_name = 'x2')
writer.save()
writer.close()

这里我生成了一个excel文件,据我了解,它是通过“xslxwriter”还是“openpyxl”引擎生成的并不重要。

当我想写而不丢失原始数据时

import pandas as pd
import numpy as np
from openpyxl import load_workbook

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

book = load_workbook(path)
writer = pd.ExcelWriter(path, engine = 'openpyxl')
writer.book = book

x3 = np.random.randn(100, 2)
df3 = pd.DataFrame(x3)

x4 = np.random.randn(100, 2)
df4 = pd.DataFrame(x4)

df3.to_excel(writer, sheet_name = 'x3')
df4.to_excel(writer, sheet_name = 'x4')
writer.save()
writer.close()

这段代码完成了这项工作!

【讨论】:

任何想法,为什么当我尝试这个时我得到:ValueError: No Excel writer 'Sales Leads Calculations.xlsx'? 是的,这是将工作表添加到 Excel 中,而不会清除现有工作表。谢谢! 保存excel文件时,如何保留已有的excel表格格式? 如果有人读到这篇文章并想知道如何用相同名称覆盖现有工作表而不是重命名新工作表:在writer.book = book 之后添加行writer.sheets = dict((ws.title, ws) for ws in book.worksheets) @Stefano Fedele 你能用'xlsxwriter'而不是'openpyxl'对现有的excel做同样的更新吗?【参考方案4】:

一次将多个数据写入 Excel 的简单示例。并且当您想将数据附加到书面 excel 文件(已关闭的 excel 文件)上的工作表时。

当你第一次写 Excel 时。 (将“df1”和“df2”写入“1st_sheet”和“2nd_sheet”)

import pandas as pd 
from openpyxl import load_workbook

df1 = pd.DataFrame([[1],[1]], columns=['a'])
df2 = pd.DataFrame([[2],[2]], columns=['b'])
df3 = pd.DataFrame([[3],[3]], columns=['c'])

excel_dir = "my/excel/dir"

with pd.ExcelWriter(excel_dir, engine='xlsxwriter') as writer:    
    df1.to_excel(writer, '1st_sheet')   
    df2.to_excel(writer, '2nd_sheet')   
    writer.save()    

关闭 excel 后,但您希望在同一个 excel 文件但另一个工作表上“附加”数据,假设“df3”到工作表名称“3rd_sheet”。

book = load_workbook(excel_dir)
with pd.ExcelWriter(excel_dir, engine='openpyxl') as writer:
    writer.book = book
    writer.sheets = dict((ws.title, ws) for ws in book.worksheets)    

    ## Your dataframe to append. 
    df3.to_excel(writer, '3rd_sheet')  

    writer.save()     

注意excel格式不能是xls,可以用xlsx一个。

【讨论】:

我看不出这个答案增加了什么。事实上,像这样重复使用上下文管理器会涉及更多的 I/O。【参考方案5】:

您可以将您感兴趣的现有工作表(例如“x1”、“x2”)读入内存,然后在添加更多新工作表之前将它们“写回”(请记住,文件中的工作表和内存中的工作表是两个不同的东西,如果你不阅读它们,它们就会丢失)。此方法仅使用“xlsxwriter”,不涉及 openpyxl。

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

# begin <== read selected sheets and write them back
df1 = pd.read_excel(path, sheet_name='x1', index_col=0) # or sheet_name=0
df2 = pd.read_excel(path, sheet_name='x2', index_col=0) # or sheet_name=1
writer = pd.ExcelWriter(path, engine='xlsxwriter')
df1.to_excel(writer, sheet_name='x1')
df2.to_excel(writer, sheet_name='x2')
# end ==>

# now create more new sheets
x3 = np.random.randn(100, 2)
df3 = pd.DataFrame(x3)

x4 = np.random.randn(100, 2)
df4 = pd.DataFrame(x4)

df3.to_excel(writer, sheet_name='x3')
df4.to_excel(writer, sheet_name='x4')
writer.save()
writer.close()

如果你想保留所有现有的工作表,你可以将上面的代码替换为:

# read all existing sheets and write them back
writer = pd.ExcelWriter(path, engine='xlsxwriter')
xlsx = pd.ExcelFile(path)
for sheet in xlsx.sheet_names:
    df = xlsx.parse(sheet_name=sheet, index_col=0)
    df.to_excel(writer, sheet_name=sheet)

【讨论】:

【参考方案6】:
#This program is to read from excel workbook to fetch only the URL domain names and write to the existing excel workbook in a different sheet..
#Developer - Nilesh K
import pandas as pd
from openpyxl import load_workbook #for writting to the existing workbook

df = pd.read_excel("urlsearch_test.xlsx")

#You can use the below for the relative path.
# r"C:\Users\xyz\Desktop\Python\

l = [] #To make a list in for loop

#begin
#loop starts here for fetching http from a string and iterate thru the entire sheet. You can have your own logic here.
for index, row in df.iterrows():
    try: 
        str = (row['TEXT']) #string to read and iterate
        y = (index)
        str_pos = str.index('http') #fetched the index position for http
        str_pos1 = str.index('/', str.index('/')+2) #fetched the second 3rd position of / starting from http
        str_op = str[str_pos:str_pos1] #Substring the domain name
        l.append(str_op) #append the list with domain names

    #Error handling to skip the error rows and continue.
    except ValueError:
            print('Error!')
print(l)
l = list(dict.fromkeys(l)) #Keep distinct values, you can comment this line to get all the values
df1 = pd.DataFrame(l,columns=['URL']) #Create dataframe using the list
#end

#Write using openpyxl so it can be written to same workbook
book = load_workbook('urlsearch_test.xlsx')
writer = pd.ExcelWriter('urlsearch_test.xlsx',engine = 'openpyxl')
writer.book = book
df1.to_excel(writer,sheet_name = 'Sheet3')
writer.save()
writer.close()

#The below can be used to write to a different workbook without using openpyxl
#df1.to_excel(r"C:\Users\xyz\Desktop\Python\urlsearch1_test.xlsx",index='false',sheet_name='sheet1')

【讨论】:

我没有关注这与问题的关系,除了它关于 excel。 我正在努力寻找一个完整的解决方案来读取和写入现有工作簿,但找不到相同的解决方案。在这里,我找到了有关如何写入现有工作簿的提示,因此我想为我的问题提供完整的解决方案。希望它清楚。【参考方案7】:

另一种相当简单的方法是制作这样的方法:

def _write_frame_to_new_sheet(path_to_file=None, sheet_name='sheet', data_frame=None):
    book = None
    try:
        book = load_workbook(path_to_file)
    except Exception:
        logging.debug('Creating new workbook at %s', path_to_file)
    with pd.ExcelWriter(path_to_file, engine='openpyxl') as writer:
        if book is not None:
            writer.book = book
        data_frame.to_excel(writer, sheet_name, index=False)

这里的想法是在 path_to_file 处加载工作簿(如果存在),然后将 data_frame 附加为带有 sheet_name 的新工作表。如果工作簿不存在,则创建它。似乎 openpyxlxlsxwriter 都没有追加,因此在上面@Stefano 的示例中,您确实必须加载然后重写才能追加。

【讨论】:

import logging import pandas as pd import openpyxl def write_frame_to_new_sheet(path_to_file=None, sheet_name='sheet', data_frame=None): book = None try: book = openpyxl.load_workbook(path_to_file) 例外: logging.debug('Creating new workbook at %s', path_to_file) with pd.ExcelWriter(path_to_file, engine='openpyxl') as writer: if book is not None: writer.book = book data_frame.to_excel(writer, sheet_name, index=False)【参考方案8】:

不用ExcelWriter也能做到,使用openpyxl中的工具 这可以使使用openpyxl.styles向新工作表中添加字体更加容易

import pandas as pd
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows

#Location of original excel sheet
fileLocation =r'C:\workspace\data.xlsx'

#Location of new file which can be the same as original file
writeLocation=r'C:\workspace\dataNew.xlsx'

data = 'Name':['Tom','Paul','Jeremy'],'Age':[32,43,34],'Salary':[20000,34000,32000]

#The dataframe you want to add
df = pd.DataFrame(data)

#Load existing sheet as it is
book = load_workbook(fileLocation)
#create a new sheet
sheet = book.create_sheet("Sheet Name")

#Load dataframe into new sheet
for row in dataframe_to_rows(df, index=False, header=True):
    sheet.append(row)

#Save the modified excel at desired location    
book.save(writeLocation)

【讨论】:

这是一个不错的解决方案,但我不确定这是否也是一种暗示。你的意思是你不能用ExcelWriter 做,或者你不需要? 您可以使用 Excelwriter 来完成,但我发现使用 openpyxl 会更容易。【参考方案9】:

用于创建新文件

x1 = np.random.randn(100, 2)
df1 = pd.DataFrame(x1)
with pd.ExcelWriter('sample.xlsx') as writer:  
    df1.to_excel(writer, sheet_name='x1')

要附加到文件,请在pd.ExcelWriter 中使用参数mode='a'

x2 = np.random.randn(100, 2)
df2 = pd.DataFrame(x2)
with pd.ExcelWriter('sample.xlsx', engine='openpyxl', mode='a') as writer:  
    df2.to_excel(writer, sheet_name='x2')

默认为mode ='w'。 见documentation。

【讨论】:

这个解决方案没有覆盖我以前的工作表。【参考方案10】:
import pandas as pd
import openpyxl

writer = pd.ExcelWriter('test.xlsx', engine='openpyxl')
data_df.to_excel(writer, 'sheet_name')
writer.save()
writer.close()

【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票 @RanMarciano 的反馈总是很重要。但在这里尤其重要,还有其他九个答案,包括一个接受了超过一百个赞的答案。为什么需要新的答案?您的方法何时可能比现有答案更可取?您是否利用了提交原始答案时不可用的新 API?如果没有这些信息,读者就不太可能理解他们何时或为什么应该尝试这种方法。你能编辑你的答案吗?【参考方案11】:

每次您想将 Pandas DataFrame 保存到 Excel 时,都可以调用此函数:

import os

def save_excel_sheet(df, filepath, sheetname, index=False):
    # Create file if it does not exist
    if not os.path.exists(filepath):
        df.to_excel(filepath, sheet_name=sheetname, index=index)

    # Otherwise, add a sheet. Overwrite if there exists one with the same name.
    else:
        with pd.ExcelWriter(filepath, engine='openpyxl', if_sheet_exists='replace', mode='a') as writer:
            df.to_excel(writer, sheet_name=sheetname, index=index)

【讨论】:

以上是关于如何使用 Pandas 在现有的 excel 文件中保存新工作表?的主要内容,如果未能解决你的问题,请参考以下文章