【问题标题】:Writing Dataframes to Different excel Sheets将数据框写入不同的 Excel 表格
【发布时间】:2018-08-13 20:33:01
【问题描述】:

我正在网络上抓取一些数据并将其写入大约 6 个数据帧。然后,我想将这些数据帧中的每一个写入 Excel 文件中的单独工作表。我在网上查看并尝试了两种不同的方法,但无法得到我想要的结果。如果我使用以下代码,它只会将最后一个数据帧写入 excel,其他所有内容都会被覆盖:

book = "Sample.xlsx"
rb = openpyxl.load_workbook(book)
rb.create_sheet(pitches[x] + ' Data')
activeSheet = pitches[x] + ' Data'
writer = pd.ExcelWriter(book, engine='xlsxwriter')
combinedDF.to_excel(writer, sheet_name=activeSheet,  index=False)
writer.save()

如果我使用以下代码部分,它会创建每个单独的工作表,但不会将数据框数据写入 excel 文件:

book = "Sample.xlsx"
rb = openpyxl.load_workbook(book)
rb.create_sheet(pitches[x] + ' Data')
activeSheet = pitches[x] + ' Data'
combinedDF.to_excel(book, sheet_name=activeSheet,  index=False)
rb.save(book)

这里是完整的代码:

from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
import time
from bs4 import BeautifulSoup
import requests
import pandas as pd
import openpyxl
book = "Baseball Savant Data.xlsx"
rb = openpyxl.load_workbook(book)
pitches = ['Fastball', '2 Seam Fastball', 'Cut Fastball', 'Split-Finger 
Fastball', 'Sinker', 'Slider', 'Changeup', 'Curveball']


beginningTime = time.time()
browser = webdriver.Chrome()
browser.get('http://www.baseballsavant.com')
browser.maximize_window()
linkPage = browser.find_element_by_link_text('Statcast Search')
linkPage.click()
time.sleep(2)
myMinimumPitchCount = browser.find_element_by_xpath("""//*
[@id="min_pitches"]/option[@value='500']""").click()

myMinimumResultCount= browser.find_element_by_xpath("""//*
[@id="min_results"]/option[@value='50']""").click()

pitchCode = ['FF','FT','FC','FS','SI','SL','CH','CU']
time.sleep(2)
x = 0
y = 0


while x < len(pitchCode):
    if x == 0:
        current = ('chk_PT_' + pitchCode[x])
        pitchSelection = browser.find_element_by_class_name("mock-pulldown-
container")
        pitchSelection.click()
        currentPitch = browser.find_element_by_id(current).click()
        searchButton = browser.find_element_by_xpath("""//*
[@id="pfx_form"]/div[2]/div/input[1]""").click()
        time.sleep(3)

        while y < 2:
            if y == 0:
                currentURL = browser.current_url
                r = requests.get(currentURL)
                soup=BeautifulSoup(r.text, "html.parser")
                table_headers_data = soup.find("table", {"id" : 
"search_results"})
                statistics = soup.findAll("tr", {"class" : "search_row"})

                table_headers = [th.text.strip() for th in 
table_headers_data.findAll('th')[0:5]]
                data_rows = statistics[:]
                player_data = [[td.text.strip() for td in 
data_rows[i].findAll('td')[0:5]]
                    for i in range(len(data_rows))]

                dfPitchCount = pd.DataFrame(player_data, index=None, 
columns=table_headers)
                print('Y = ' + str(y))
                y+=1


            elif y != 0:
                wOBAAllowed = browser.find_element_by_xpath("""//*
[@id="sort_col"]/option[@value='woba']""").click()
                searchButton = browser.find_element_by_xpath("""//*
[@id="pfx_form"]/div[2]/div/input[1]""").click()
                time.sleep(2)
                currentURL = browser.current_url
                r = requests.get(currentURL)
                soup=BeautifulSoup(r.text, "html.parser")
                table_headers_data = soup.find("table", {"id" : 
"search_results"})
                statistics = soup.findAll("tr", {"class" : "search_row"})


                table_headers = [th.text.strip() for th in 
table_headers_data.findAll('th')[0:4]]

                data_rows = statistics[:]
                player_data = [[td.text.strip() for td in 
data_rows[i].findAll('td')[0:4]]
                   for i in range(len(data_rows))]

                dfwOBA = pd.DataFrame(player_data, index=None, 
columns=table_headers)
                combinedDF = pd.merge(dfPitchCount, dfwOBA, how='left', 
on="Player", sort=False, indicator = "True")
                print(rb.get_sheet_names())

                rb.create_sheet(pitches[x] + ' Data')
                activeSheet = pitches[x] + ' Data'
                writer = pd.ExcelWriter(book, engine='xlsxwriter')
                combinedDF.to_excel(writer, sheet_name=activeSheet, 
index=False )
                writer.save()
                pitchSort = browser.find_element_by_xpath("""//*
[@id="sort_col"]/option[@value='pitches']""").click()
                print('Y = ' + str(y))
                y+=1
                print('this is ' + str(x))
                x+=1


    elif x != 0:
        y=0
        print('y boogers = ' + str(y))
        pitchSelection = browser.find_element_by_class_name("mock-pulldown-
container")
        pitchSelection.click()
        time.sleep(5)
        current = ('chk_PT_' + pitchCode[x])
        previous = ('chk_PT_' + pitchCode[x-1])
        previousPitch = browser.find_element_by_id(previous)
        previousPitch.click()
        time.sleep(1)
        print(current)        
        pitchSelection.click()
        currentPitch = browser.find_element_by_id(current)
        currentPitch.click()
        time.sleep(1)
        print(previous)
        pitchSort = browser.find_element_by_xpath("""//*
[@id="sort_col"]/option[@value='pitches']""").click()
        searchButton = browser.find_element_by_xpath("""//*
[@id="pfx_form"]/div[2]/div/input[1]""").click()

        while y < 2:
            if y == 0:
                currentURL = browser.current_url
                r = requests.get(currentURL)
                soup=BeautifulSoup(r.text, "html.parser")
                table_headers_data = soup.find("table", {"id" : 
"search_results"})
                statistics = soup.findAll("tr", {"class" : "search_row"})

                table_headers = [th.text.strip() for th in 
table_headers_data.findAll('th')[0:5]]
                data_rows = statistics[:]
                player_data = [[td.text.strip() for td in 
data_rows[i].findAll('td')[0:5]]
                    for i in range(len(data_rows))]

                dfPitchCount = pd.DataFrame(player_data, index=None, 
columns=table_headers)

                y+=1

            elif y != 0:
                wOBAAllowed = browser.find_element_by_xpath("""//*
[@id="sort_col"]/option[@value='woba']""").click()
                searchButton = browser.find_element_by_xpath("""//*
[@id="pfx_form"]/div[2]/div/input[1]""").click()
                time.sleep(2)
                currentURL = browser.current_url
                r = requests.get(currentURL)
                soup=BeautifulSoup(r.text, "html.parser")
                table_headers_data = soup.find("table", {"id" : 
"search_results"})
                statistics = soup.findAll("tr", {"class" : "search_row"})


                table_headers = [th.text.strip() for th in 
table_headers_data.findAll('th')[0:4]]

                data_rows = statistics[:]
                player_data = [[td.text.strip() for td in 
data_rows[i].findAll('td')[0:4]]
                   for i in range(len(data_rows))]

                dfwOBA = pd.DataFrame(player_data, index=None, 
columns=table_headers)
                combinedDF = pd.merge(dfPitchCount, dfwOBA, how='left', 
on="Player", sort=False, indicator = "True")
                print(combinedDF)
                print(rb.get_sheet_names())

                rb.create_sheet(pitches[x] + ' Data')
                activeSheet = pitches[x] + ' Data'
                writer = pd.ExcelWriter(book, engine='xlsxwriter')

                combinedDF.to_excel(writer, sheet_name=activeSheet,  
index=False)
                writer.save()
                pitchSort = browser.find_element_by_xpath("""//*
[@id="sort_col"]/option[@value='pitches']""").click()

                y+=1

                x+=1

【问题讨论】:

  • 什么是x?也许是一个循环?
  • 是的,它是一个循环 - 还有一堆其他代码,但其他一切似乎都很好。它的编写效率也不是很高,所以我计划修复其中的一些问题,但只需要帮助弄清楚它为什么会覆盖工作表或为什么它没有在第二个代码中写入数据。
  • 如果有循环,则需要在示例中显示循环。
  • 我可以添加所有这些,但是代码效率不是很高,我不一定认为它是完全必要的。循环工作正常。在第二个示例中,它循环遍历并按应有的方式命名每个工作表;但是,由于未将数据帧数据写入工作表,因此工作表为空。在第一个示例中,循环正常工作,但循环中的最后一项是唯一剩下的工作表。因此,我想知道如何使用 pandas 和 openpyxl 将每个数据帧写入单独的 excel 表。
  • No 是要求甚至想要“all that” 足以证明问题。您可以学习 How to Ask a good question 并创建一个 Minimal, Complete, and Verifiable 示例。这让我们更容易为您提供帮助。

标签: python excel pandas dataframe openpyxl


【解决方案1】:

您似乎错过了最重要的来源:to_excel 的 pandas 文档:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_excel.html

所以,把writer = pd.ExcelWriter(book, engine='xlsxwriter') 和writer.save() 放到循环之外:第一个在开始x 循环之前,第二个在它之后:你应该只打开并保存一次excel文件,而不是每张表写。

【讨论】:

  • 我确实查看了 to_excel 的文档,但我想我没有弄明白。我对 python 还是比较陌生,但我试图研究它。尽管将作者置于循环之外是有道理的 - 我今天下班后会尝试并将您的答案标记为正确。事后看来,这似乎很明显——我尝试遍历我的代码以确保它正在做我认为应该做的一切,但我仍然错过了这一点。关于如何遍历代码以确保它真正按照您的意图执行的任何提示/技巧?
  • 诀窍是编写可读的代码。慢慢来。有时我会阻止自己几分钟,思考一个好的变量名。可读的代码有助于发现错误。我不知道您的代码中的 x 和 y 是什么意思。你的while 和for.. range(len(..)) 应该写得更像pythonic。我在你的代码上闻到了很多 C 的味道。经验有帮助:编写和调试大量代码,从其他人那里读取代码(例如示例、博客,以及 github 中的真实代码)
  • 我唯一的经验是使用 VBA,而且也很有限,所以我对编码很陌生,没有 C 经验。我知道有很多重复的代码,所以我打算尝试编写一个它的部分功能。我想我在试图为自己完成一个特定的项目时被抓住了,我太新了,我只做我知道有效的事情或我在网上找到的事情。我想 x 和 y 不一定意味着任何东西,如果有意义的话,它们只是循环的机制?如果你有时间,你能举一个写 while 和 for 循环更 Pythonic 的例子吗?非常感谢您的反馈。
猜你喜欢
  • 1970-01-01
  • 2019-03-23
  • 2019-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
相关资源
最近更新 更多