[英]How to parse dataframes from an excel sheet with many tables (using Python, possibly Pandas)
我正在處理布局糟糕的excel表,我正在嘗試解析並寫入數據庫。
每張表都可以有多個表。 雖然這些可能的表格的標題是已知的,但是哪些表格將在任何給定的表格上都沒有,它們在表格上的確切位置也不是(表格不以一致的方式對齊)。 我添加了兩張可能的工作表布局的圖片來說明這一點: 這個布局有兩個表,而這個表有第一個表,但不在同一個位置,加上一個額外的表。
我所知道的:
我的問題是否有一種干凈的方法來處理這個使用一些Python模塊,如熊貓?
我目前的做法 :
我目前正在轉換為.csv並解析每一行。 我將每一行分成空白單元格,然后處理行的第一部分(應該屬於最左邊的表格)。 行的其余部分排隊,然后以相同的方式處理。 然后我讀了這個first_part
並檢查它是否是標題行。 如果是,我用它來識別我正在處理的表(這是存儲在全局current_df
)。 不是標題行的后續行被送入此表(這里我使用pandas.DataFrame
表示我的表)。
到目前為止的代碼如下(大部分是不完整和未經測試的,但它應該傳達上述方法):
class DFManager(object): # keeps track of current table and its headers
current_df = None
current_headers = []
def set_current_df(self, df, headers):
self.current_headers = headers
self.current_df = df
def split_row(row, separator):
while row and row[0] == separator:
row.pop(0)
while row and row[-1] == separator:
row.pop()
if separator in row:
split_index = row.index(separator)
return row[:split_index], row[split_index:]
else:
return row, []
def process_df_row(row, dfmgr):
df = df_with_header(row) # returns the dataframe with these headers
if df is None: # is not a header row, add it to current df
df = dfmgr.current_df
add_row_to_df(row, df)
else:
dfmgr.set_current_df(df, row)
# this is passed the Excel sheet
def populate_dataframes(xl_sheet):
dfmgr = DFManager()
row_queue = Queue()
for row in xl_sheet:
row_queue.put(row)
for row in iter(row_queue.get, None):
if not row:
continue
first_part, remainder = split_row(row)
row_queue.put(remainder)
process_df_row(first_part, dfmgr)
這是一個特殊的情況,使用現成的模塊可能沒有“干凈”的方法來做到這一點。
一種方法可能會使用您已有的頭信息來查找每個表的起始索引,類似於此解決方案( Python Pandas - 讀取包含多個表的csv文件 ),但在列方向上也有偏移量。
一旦有了每個表的起始位置,就需要確定寬度(先驗已知或通過讀取直到下一個空白列發現)並將這些列讀入數據幀直到表的末尾。
基於索引的方法而不是基於隊列的方法的好處是您不需要重新發現每行中分隔符的位置,也不需要跟蹤哪些行片段屬於哪個表。 每行> 2個表的存在也是不可知的。
我編寫代碼來合並垂直分隔的多個表,每個表中都有公共標題。 我假設唯一標題應該名稱不以點整數來結束。 “””
def clean(input_file, output_file):
try:
df = pd.read_csv(input_file, skiprows=[1,1])
df = df.drop(df.columns[df.columns.str.contains('unnamed',case = False)],axis=1)
df = rename_duplicate_columns(df)
except:
df =[]
print("Error: File Not found\t", sys.exc_info() [0])
exit
udf = df.loc[:, ~df.columns.str.match(".*\.\d")]
udf = udf.dropna(how='all')
try:
table_num = int(df.columns.values[-1].split('.')[-1])
fdf = udf
for i in range(1,table_num+1):
udfi = pd.DataFrame()
udfi = df.loc[:, df.columns.str.endswith(f'.{i}')]
udfi.rename(columns = lambda x: '.'.join(x.split('.')[:-1]), inplace=True)
udfi = udfi.dropna(how='all')
fdf = fdf.append(udfi,ignore_index=True)
fdf.to_csv(output_file)
except ValueError:
print ("File Contains only single Table")
exit
def rename_duplicate_columns(df):
cols=pd.Series(df.columns)
for dup in df.columns.get_duplicates():
cols[df.columns.get_loc(dup)]=[dup+'.'+str(d_idx) if d_idx!=0 else
dup for d_idx in range(df.columns.get_loc(dup).sum())]
df.columns=cols
print(df.columns)
return df
clean(input_file, output_file)
“””
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.