Таким образом, после того, как я рассмотрю более подход, который я использовал для очистки, выглядит следующим образом:
Загрузка в df, заголовков нет, поэтому столбцы - это всего лишь 0,1,2 лота NaN и т. Д.
Удалите все столбцы, которые являются NaN
df2 = df.dropna(axis = 0, how ='all').copy()
Я хотел сохранить название компании, но не другие данные, такие как заголовок отчета или округ, поэтому разделите строку, чтобы удалитьтекст, который я не хотел, а затем создал маску для строк, содержащих Мексику, а затем отфильтровал df, чтобы удалить их
df2[0] = df2[0].str.split(' ').str[0]
mask = (df2[0] == 'Mexico')
df3 = df3[~mask].copy()
Затем использовал ffill, чтобы скопировать название компании в каждую строку df (тамявляются несколькими названиями компаний, отчет делает все записи для одной компании, затем для следующей и т. д.)
df3[0]=df3[0].fillna(method='ffill')
Столбец [1] содержит данные для родительской записи Cnno и дочерних записей Pstdte, эточисловые данные хранятся в виде текста, поэтому я отфильтровал этот столбец с помощью to_numeric, это удаляет все строки заголовков и номеров страниц, которые повторяются, хотя из данных остаются только родитель и потомокстрок.
df4 = df3[new_WHT2[[1]].apply(pd.to_numeric, errors='coerce').notnull().all(axis=1)].copy()
Затем я создал новый столбец 'Cnno' и заполнил его, используя
df4.loc[new_WHT3[1]<9999, 'Cnno'] = df4[1]
, и Cnno, и Pstdte являются числами, но поскольку Pstdte является "датой",минимальная длина равна 5, а Cnno никогда не превышает длину 4, поэтому я мог бы использовать это для разделения родительских и дочерних строк
Поскольку за каждой родительской строкой следуют ее дочерние элементы в кадре данных, я мог бы использовать ffill для'Cnno', чтобы скопировать родительский Cnno к его дочерним элементам, чтобы связать записи
df4['Cnno'] = df4['Cnno'].fillna(method='ffill')
Затем я создал родительский столбец для идентификации родительских записей (не обязательно)
df4['Parent'] = (df4[1]<9999).astype(int)
Затем я отфильтровал родительский столбец и скопировал данные в новый файл df, удалил все пустые данные, удалил старые данные для cnno в столбце [1] и добавил новые заголовки столбцов для остальных.Поскольку родительская строка повторяется при появлении новой страницы в исходном файле, было несколько строк с одинаковыми данными, поэтому я отбросил дубликаты, оставив только первую
Parent = df4[df4['Parent'] == 1].copy()
Parent = Parent.dropna(axis=1, how='all')
Parent = Parent.drop(Parent.columns[1] , axis=1)
Parent.columns = ['Company','Account No','Tax Code','Vendor Address','Cnno','Parent']
Parent.drop_duplicates(keep='first', inplace=True)
. Затем получим чистую dfтолько родительские записи
Company, Account No, Tax Code, Vendor Address, Cnno, Parent
5 ACME Ltd, ABC3415, 899111752, Kellys Hair ONE ST JOHNS CHURCHYARD ED45 8LP LONDON, 1, 1
18 ACME Ltd, BFG4919, 7880487069, SPA LTD OHNSON HOUSE GREENBY SQHH1 3DF READING, 2, 1
Затем я в основном сделал то же самое с дочерними записями
Children = df4[df4['Parent'] != 1].copy()
Children = Children.dropna(axis=1, how='all')
Children.columns = ['Company','PstDte', 'DocNo','DocDte','Reference no','ClgDte','WT code','Invoice amnt','Base amount','tax','Net amount','T x-exempt amt','Cnno','Parent']
Это дало мне чистую df всех дочерних записей, затем я объединил родителя идочерние записи, используя ключ company и cnno
Final = pd.merge(Parent, Children, how='left', left_on=['Company','Cnno'], right_on = ['Company','Cnno'])
После этого это был всего лишь случай форматирования каждого из столбцов даты и любых других битов форматирования, dtypes и т. д.
Final['PstDte'] = Final['PstDte'].apply(lambda x: pd.to_datetime(str(x), format='%d%m%y'))