У меня есть несколько книг Excel, каждая из которых содержит несколько рабочих листов, которые я хотел бы объединить.
Я создал два набора циклов (один, один, один для), чтобы читать строки для каждого листа в данной книге, а затем делать то же самое для всех книг.
Я попытался сделать это на подмножестве, и, похоже, он работает до тех пор, пока я не попытаюсь объединить два набора, используя функцию pd.concat. Приведенная ошибка
TypeError: первый аргумент должен быть итерабельным из объектов pandas, вы передали объект типа "DataFrame",
Любая идея, что я делаю неправильно?
import pandas as pd
d = 2013
numberOfSheets = 5
while d < 2015:
#print(str(d) + ' beginning')
f ='H:/MyDocuments/Z Project Work/scriptTest ' + str(d) + '.xlsx'
for i in range(1,numberOfSheets+1):
data = pd.read_excel(f, sheetname = 'Table '+str(i), header=None)
print(i)
df.append(data)
print(str(d) + ' complete')
print(df)
d += 1
df = pd.concat(df)
print(df)
final = "H:/MyDocuments/Z Project Work/mergedfile.xlsx"
df.to_excel(final)
Как говорит ошибка, pd.concat()
требует итерации, как и список: pd.concat([df1, df2])
объединяет df1
и df2
вдоль оси по умолчанию 0, что означает, что df2
добавляется к нижней части df1
,
Необходимо решить две проблемы:
for
ссылается на df
перед назначением ему чего-либо.df
перезаписывается каждой итерацией цикла for
.Один из способов - создать пустой список DataFrames перед циклами, затем добавить DataFrames в этот список и, наконец, объединить все DataFrames в этом списке. Что-то вроде этого:
import pandas as pd
d = 2013
numberOfSheets = 5
dfs = []
while d < 2015:
#print(str(d) + ' beginning')
f ='H:/MyDocuments/Z Project Work/scriptTest ' + str(d) + '.xlsx'
for i in range(1, numberOfSheets + 1):
data = pd.read_excel(f, sheetname='Table ' + str(i), header=None)
print(i)
dfs.append(data)
print(str(d) + ' complete')
print(df)
d += 1
# ignore_index=True gives the result a default IntegerIndex
# starting from 0
df_final = pd.concat(dfs, ignore_index=True)
print(df_final)
final_path = "H:/MyDocuments/Z Project Work/mergedfile.xlsx"
df_final.to_excel(final_path)
Поскольку я не могу комментировать, я оставлю это в качестве ответа: вы можете ускорить этот код, открыв файл, после чего разберем книгу, чтобы получить каждый лист. Следует сохранять секунду или две с каждой итерации, так как открытие файла Excel занимает самое большое время. Вот код, который может помочь.
Примечание: установка sheet_name=None
вернет ВСЕ листы в книге:
dfs = {<sheetname1>: <DataFrame1>, <sheetname2>: <DataFrame2>, etc.}
Здесь код:
xl = pd.ExcelFile(fpath)
dfs = xl.parse(sheetname=None, header=None)
for i, df in enumerate(dfs):
<do stuff with each, if you want>
print('Sheet {0} looks like:\n{1}'.format(i+1, df))
Спасибо вам обоим. Я принял ответ, который касался конкретного вопроса, но был в состоянии использовать второй ответ и некоторый дополнительный googling после этого (например, glob), чтобы исправить исходный код, и автоматизировать более полную независимость от количества книг или рабочих листов.
Окончательный вариант вышеизложенного ниже:
import pandas as pd
import glob
#import numpy as np
#import os, collections, csv
#from os.path import basename
fpath = "H:/MyDocuments/Z Project Work/"
dfs = []
files = glob.glob(fpath+'*.xlsx')
for f in files:
xl = pd.ExcelFile(f)
xls = xl.parse(sheetname=None, header=0)
for i, df in enumerate(xls):
print(i)
dfs.append(xls[df])
print(f+ ' complete')
df_final = pd.concat(dfs, ignore_index=True)
final = "H:/MyDocuments/Z Project Work/mergedfile.xlsx"
df_final.to_excel(final)