hier

Code for dealing with multiindexed columns

In order to avoid circular dependencies in the resulting Python modules, and since this is only for testing

import sproc.xml

Directory where the data (XML files) are stored

directory = pathlib.Path.cwd().parent / 'samples'
assert directory.exists()
directory
PosixPath('/home/manu/Sync/UC3M/proyectos/2022/nextProcurement/sproc/samples')

A (sample) file in that directory

xml_file = directory / 'PlataformasAgregadasSinMenores_20220104_030016_1.atom'
assert xml_file.exists()
xml_file
PosixPath('/home/manu/Sync/UC3M/proyectos/2022/nextProcurement/sproc/samples/PlataformasAgregadasSinMenores_20220104_030016_1.atom')

Root element of the XML tree

root = etree.parse(xml_file).getroot()

Entries are extracted

entries = sproc.xml.get_entries(root)
assert len(entries) == 117
entries[:4]
[<Element {http://www.w3.org/2005/Atom}entry>,
 <Element {http://www.w3.org/2005/Atom}entry>,
 <Element {http://www.w3.org/2005/Atom}entry>,
 <Element {http://www.w3.org/2005/Atom}entry>]

The first one is picked out

element = entries[0]
sproc.xml.split_namespace_tag(element.tag)
('http://www.w3.org/2005/Atom', 'entry')

It is turned into a pd.Series

element_series = sproc.xml.entry_to_series(element)
element_series[:8]
id                                                                           https://contrataciondelestado.es/sindicacion/P...
summary                                                                      Id licitación: C. 2-2021; Órgano de Contrataci...
title                                                                        L'objecte del contracte és la renovació de tot...
updated                                                                                          2022-01-03T01:11:41.826+01:00
ContractFolderStatus - ContractFolderID                                                                              C. 2-2021
ContractFolderStatus - ContractFolderStatusCode                                                                            ADJ
ContractFolderStatus - LocatedContractingParty - BuyerProfileURIID           https://contractaciopublica.gencat.cat/ecofin_...
ContractFolderStatus - LocatedContractingParty - Party - PartyName - Name                             Ajuntament de Sant Ramon
dtype: object

Series

We can easily iterate the series

next(iter(element_series.items()))
('id',
 'https://contrataciondelestado.es/sindicacion/PlataformasAgregadasSinMenores/8799346')
index_paths = []
values = []
for i, v in element_series.items():
    index_paths.append(tuple(i.split(sproc.structure.nested_tags_separator)))
    values.append(v)
index_paths[:6]
[('id',),
 ('summary',),
 ('title',),
 ('updated',),
 ('ContractFolderStatus', 'ContractFolderID'),
 ('ContractFolderStatus', 'ContractFolderStatusCode')]
values[:6]
['https://contrataciondelestado.es/sindicacion/PlataformasAgregadasSinMenores/8799346',
 'Id licitación: C. 2-2021; Órgano de Contratación: Ajuntament de Sant Ramon; Importe: 135553.26; Estado: ADJUDICADA',
 "L'objecte del contracte és la renovació de totes les llumeneres que formen la il·luminació existent de tots els carrers i vials del casc urbà de la localitat de Sant Ramon i dels nuclis agregats de La Manresana, Portell, Viver i Gospí",
 '2022-01-03T01:11:41.826+01:00',
 'C. 2-2021',
 'ADJ']
multiindex = pd.MultiIndex.from_tuples(index_paths)
multiindex[:6]
MultiIndex([(                  'id',                        nan, nan, ...),
            (             'summary',                        nan, nan, ...),
            (               'title',                        nan, nan, ...),
            (             'updated',                        nan, nan, ...),
            ('ContractFolderStatus',         'ContractFolderID', nan, ...),
            ('ContractFolderStatus', 'ContractFolderStatusCode', nan, ...)],
           )
multiindexed_series = pd.Series(values, index=multiindex)
multiindexed_series[:6]
id                    NaN                       NaN  NaN  NaN    https://contrataciondelestado.es/sindicacion/P...
summary               NaN                       NaN  NaN  NaN    Id licitación: C. 2-2021; Órgano de Contrataci...
title                 NaN                       NaN  NaN  NaN    L'objecte del contracte és la renovació de tot...
updated               NaN                       NaN  NaN  NaN                        2022-01-03T01:11:41.826+01:00
ContractFolderStatus  ContractFolderID          NaN  NaN  NaN                                            C. 2-2021
                      ContractFolderStatusCode  NaN  NaN  NaN                                                  ADJ
dtype: object

A function that turns the index of a pd.Series into a hierarchical (pd.MultiIndex) one.


source

flat_series_to_multiindexed_series

 flat_series_to_multiindexed_series (s:pandas.core.series.Series)

Returns a multi-indexed version of the input

Type Details
s Series Flat series
Returns Series Multi-indexed series
flat_series_to_multiindexed_series(element_series)[:6]
id                    NaN                       NaN  NaN  NaN    https://contrataciondelestado.es/sindicacion/P...
summary               NaN                       NaN  NaN  NaN    Id licitación: C. 2-2021; Órgano de Contrataci...
title                 NaN                       NaN  NaN  NaN    L'objecte del contracte és la renovació de tot...
updated               NaN                       NaN  NaN  NaN                        2022-01-03T01:11:41.826+01:00
ContractFolderStatus  ContractFolderID          NaN  NaN  NaN                                            C. 2-2021
                      ContractFolderStatusCode  NaN  NaN  NaN                                                  ADJ
dtype: object

DataFrame

We can concatenate together the pd.Series for the different entries into a pd.DataFrame

pd.concat([flat_series_to_multiindexed_series(sproc.xml.entry_to_series(e)) for e in entries[:4]], axis=1).T
id summary title updated ContractFolderStatus
NaN NaN NaN NaN ContractFolderID ContractFolderStatusCode LocatedContractingParty ProcurementProject ... TenderResult TenderingProcess ValidNoticeInfo LegalDocumentReference
NaN NaN NaN NaN NaN NaN BuyerProfileURIID Party ParentLocatedParty Name ... WinningParty AwardedTenderedProject ProcedureCode TenderSubmissionDeadlinePeriod NoticeTypeCode AdditionalPublicationStatus ID Attachment
NaN NaN NaN NaN NaN NaN NaN PartyName PartyName NaN ... PartyName LegalMonetaryTotal NaN EndDate EndTime NaN PublicationMediaName AdditionalPublicationDocumentReference NaN ExternalReference
NaN NaN NaN NaN NaN NaN NaN Name Name NaN ... Name TaxExclusiveAmount NaN NaN NaN NaN NaN IssueDate NaN URI
0 https://contrataciondelestado.es/sindicacion/P... Id licitación: C. 2-2021; Órgano de Contrataci... L'objecte del contracte és la renovació de tot... 2022-01-03T01:11:41.826+01:00 C. 2-2021 ADJ https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Sant Ramon Entitats municipals de Catalunya L'objecte del contracte és la renovació de tot... ... AERONAVAL DE CONSTRUCCIONES I INSTALACIONES , ... 90078.51 9 2021-12-17 14:00:00 [[DOC_CN, DOC_CAN_ADJ]] [[Perfil del contratante, Perfil del contratan... [[2021-11-30, 2022-01-03]] NaN NaN
1 https://contrataciondelestado.es/sindicacion/P... Id licitación: 8128_3/2021; Órgano de Contrata... Obras de restauración hidromorfológica del río... 2022-01-03T01:00:11.194+01:00 8128_3/2021 PUB NaN Pleno del Ayuntamiento AYUNTAMIENTO DE MONREAL Obras de restauración hidromorfológica del río... ... NaN NaN 1 2022-01-22 23:30:00 DOC_CN Perfil del contratante 2022-01-03 NaN NaN
2 https://contrataciondelestado.es/sindicacion/P... Id licitación: 1000_0005-CP01-2021-000063; Órg... Contrato del servicio de realización de labore... 2022-01-03T01:00:10.399+01:00 1000_0005-CP01-2021-000063 EV NaN El Director General de Comunicación y Relacion... Departamento de Presidencia, Igualdad, Función... Contrato del servicio de realización de labore... ... NaN NaN 1 NaN NaN DOC_CN [[DOUE, Perfil del contratante]] [[2021-12-01, 2022-01-03]] NaN NaN
3 https://contrataciondelestado.es/sindicacion/P... Id licitación: 1379/2020 4738; Órgano de Contr... Obres de renovació de l'enllumenat públic a la... 2022-01-03T00:11:40.740+01:00 1379/2020 4738 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Canet de Mar Entitats municipals de Catalunya Obres de renovació de l'enllumenat públic a la... ... NaN NaN 9 2022-01-02 23:59:00 DOC_CN Perfil del contratante 2021-12-13 Plec Clausules.pdf https://contractaciopublica.gencat.cat/ecofin_...

4 rows × 29 columns

However, there is a problem if the pd.Series’s to be concatenated have different number of levels

flat_series_to_multiindexed_series(sproc.xml.entry_to_series(entries[15])).index.nlevels
5
flat_series_to_multiindexed_series(sproc.xml.entry_to_series(entries[16])).index.nlevels
6
try:
    pd.concat([flat_series_to_multiindexed_series(sproc.xml.entry_to_series(e)) for e in entries[15:17]], axis=1).T
except (ValueError, AssertionError):
    print('Oooooooooops')
Oooooooooops

The function below just converts the pd.DataFrame column-wise. Columns with different levels are handled as suggested in this post.


source

flat_df_to_multiindexed_df

 flat_df_to_multiindexed_df (input_df:pandas.core.frame.DataFrame)

Reads and parses an XML file into a DataFrame

Type Details
input_df DataFrame Input DataFrame
Returns DataFrame A column-hierarchical version of the input DataFrame

We first build the pd.DataFrame

df = sproc.xml.to_df(xml_file)
df.head(6)
id summary title updated ContractFolderStatus - ContractFolderID ContractFolderStatus - ContractFolderStatusCode ContractFolderStatus - LocatedContractingParty - BuyerProfileURIID ContractFolderStatus - LocatedContractingParty - Party - PartyName - Name ContractFolderStatus - LocatedContractingParty - ParentLocatedParty - PartyName - Name ContractFolderStatus - ProcurementProject - Name ... ContractFolderStatus - LegalDocumentReference - Attachment - ExternalReference - URI ContractFolderStatus - TechnicalDocumentReference - ID ContractFolderStatus - TechnicalDocumentReference - Attachment - ExternalReference - URI ContractFolderStatus - ProcurementProject - PlannedPeriod - StartDate ContractFolderStatus - ProcurementProject - PlannedPeriod - EndDate ContractFolderStatus - LocatedContractingParty - Party - PartyIdentification - ID ContractFolderStatus - LocatedContractingParty - ParentLocatedParty - ParentLocatedParty - PartyName - Name ContractFolderStatus - TenderingProcess - ParticipationRequestReceptionPeriod - EndDate ContractFolderStatus - TenderingProcess - ParticipationRequestReceptionPeriod - EndTime ContractFolderStatus - TenderResult - AwardedTenderedProject - ProcurementProjectLotID
0 https://contrataciondelestado.es/sindicacion/P... Id licitación: C. 2-2021; Órgano de Contrataci... L'objecte del contracte és la renovació de tot... 2022-01-03T01:11:41.826+01:00 C. 2-2021 ADJ https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Sant Ramon Entitats municipals de Catalunya L'objecte del contracte és la renovació de tot... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 https://contrataciondelestado.es/sindicacion/P... Id licitación: 8128_3/2021; Órgano de Contrata... Obras de restauración hidromorfológica del río... 2022-01-03T01:00:11.194+01:00 8128_3/2021 PUB NaN Pleno del Ayuntamiento AYUNTAMIENTO DE MONREAL Obras de restauración hidromorfológica del río... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 https://contrataciondelestado.es/sindicacion/P... Id licitación: 1000_0005-CP01-2021-000063; Órg... Contrato del servicio de realización de labore... 2022-01-03T01:00:10.399+01:00 1000_0005-CP01-2021-000063 EV NaN El Director General de Comunicación y Relacion... Departamento de Presidencia, Igualdad, Función... Contrato del servicio de realización de labore... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 https://contrataciondelestado.es/sindicacion/P... Id licitación: 1379/2020 4738; Órgano de Contr... Obres de renovació de l'enllumenat públic a la... 2022-01-03T00:11:40.740+01:00 1379/2020 4738 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Canet de Mar Entitats municipals de Catalunya Obres de renovació de l'enllumenat públic a la... ... https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 https://contrataciondelestado.es/sindicacion/P... Id licitación: 2021-44; Órgano de Contratación... Subministre i la instal·lació fotovoltaica en ... 2022-01-03T00:11:40.696+01:00 2021-44 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Valls Entitats municipals de Catalunya Subministre i la instal·lació fotovoltaica en ... ... https://contractaciopublica.gencat.cat/ecofin_... Enllac plec clausules tecniques.doc https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN
5 https://contrataciondelestado.es/sindicacion/P... Id licitación: 2809/2021; Órgano de Contrataci... Servei de visites i activitats sobre Història ... 2022-01-03T00:11:40.639+01:00 2809/2021 EV https://contractaciopublica.gencat.cat/ecofin_... Institut de Cultura de Barcelona Entitats municipals de Catalunya Servei de visites i activitats sobre Història ... ... https://contractaciopublica.gencat.cat/ecofin_... 2809-21 PPT.pdf https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN

6 rows × 38 columns

…and, afterwards, a hierarchical version thereof

hierarchical_df = flat_df_to_multiindexed_df(df)
hierarchical_df.head()
id summary title updated ContractFolderStatus
ContractFolderID ContractFolderStatusCode LocatedContractingParty ProcurementProject ... LegalDocumentReference TechnicalDocumentReference ProcurementProject LocatedContractingParty TenderingProcess TenderResult
BuyerProfileURIID Party ParentLocatedParty Name ... Attachment ID Attachment PlannedPeriod Party ParentLocatedParty ParticipationRequestReceptionPeriod AwardedTenderedProject
PartyName PartyName ... ExternalReference ExternalReference StartDate EndDate PartyIdentification ParentLocatedParty EndDate EndTime ProcurementProjectLotID
Name Name ... URI URI ID PartyName
... Name
0 https://contrataciondelestado.es/sindicacion/P... Id licitación: C. 2-2021; Órgano de Contrataci... L'objecte del contracte és la renovació de tot... 2022-01-03T01:11:41.826+01:00 C. 2-2021 ADJ https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Sant Ramon Entitats municipals de Catalunya L'objecte del contracte és la renovació de tot... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 https://contrataciondelestado.es/sindicacion/P... Id licitación: 8128_3/2021; Órgano de Contrata... Obras de restauración hidromorfológica del río... 2022-01-03T01:00:11.194+01:00 8128_3/2021 PUB NaN Pleno del Ayuntamiento AYUNTAMIENTO DE MONREAL Obras de restauración hidromorfológica del río... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 https://contrataciondelestado.es/sindicacion/P... Id licitación: 1000_0005-CP01-2021-000063; Órg... Contrato del servicio de realización de labore... 2022-01-03T01:00:10.399+01:00 1000_0005-CP01-2021-000063 EV NaN El Director General de Comunicación y Relacion... Departamento de Presidencia, Igualdad, Función... Contrato del servicio de realización de labore... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 https://contrataciondelestado.es/sindicacion/P... Id licitación: 1379/2020 4738; Órgano de Contr... Obres de renovació de l'enllumenat públic a la... 2022-01-03T00:11:40.740+01:00 1379/2020 4738 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Canet de Mar Entitats municipals de Catalunya Obres de renovació de l'enllumenat públic a la... ... https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 https://contrataciondelestado.es/sindicacion/P... Id licitación: 2021-44; Órgano de Contratación... Subministre i la instal·lació fotovoltaica en ... 2022-01-03T00:11:40.696+01:00 2021-44 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Valls Entitats municipals de Catalunya Subministre i la instal·lació fotovoltaica en ... ... https://contractaciopublica.gencat.cat/ecofin_... Enllac plec clausules tecniques.doc https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN

5 rows × 38 columns

Cross-sections of the above pd.DataFrame can be extracted

hierarchical_df.xs('id', axis='columns')
0      https://contrataciondelestado.es/sindicacion/P...
1      https://contrataciondelestado.es/sindicacion/P...
2      https://contrataciondelestado.es/sindicacion/P...
3      https://contrataciondelestado.es/sindicacion/P...
4      https://contrataciondelestado.es/sindicacion/P...
                             ...                        
112    https://contrataciondelestado.es/sindicacion/P...
113    https://contrataciondelestado.es/sindicacion/P...
114    https://contrataciondelestado.es/sindicacion/P...
115    https://contrataciondelestado.es/sindicacion/P...
116    https://contrataciondelestado.es/sindicacion/P...
Name: id, Length: 117, dtype: object

At deeper levels (notice in the above table ContractFolderID is nested inside ContractFolderStatus)

hierarchical_df.xs('ContractFolderID', axis=1, level=1)
ContractFolderStatus
0 C. 2-2021
1 8128_3/2021
2 1000_0005-CP01-2021-000063
3 1379/2020 4738
4 2021-44
... ...
112 1005_391-2021
113 8165_3/2021
114 8113_3/2021
115 8113_01 2021
116 0001264/2021

117 rows × 1 columns

The latter encompasses most of the data

hierarchical_df.xs('ContractFolderStatus', axis=1)
ContractFolderID ContractFolderStatusCode LocatedContractingParty ProcurementProject ... LegalDocumentReference TechnicalDocumentReference ProcurementProject LocatedContractingParty TenderingProcess TenderResult
BuyerProfileURIID Party ParentLocatedParty Name TypeCode BudgetAmount RequiredCommodityClassification ... Attachment ID Attachment PlannedPeriod Party ParentLocatedParty ParticipationRequestReceptionPeriod AwardedTenderedProject
PartyName PartyName EstimatedOverallContractAmount TaxExclusiveAmount ItemClassificationCode ... ExternalReference ExternalReference StartDate EndDate PartyIdentification ParentLocatedParty EndDate EndTime ProcurementProjectLotID
Name Name ... URI URI ID PartyName
... Name
0 C. 2-2021 ADJ https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Sant Ramon Entitats municipals de Catalunya L'objecte del contracte és la renovació de tot... 1 135553.26 135553.26 34928530 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 8128_3/2021 PUB NaN Pleno del Ayuntamiento AYUNTAMIENTO DE MONREAL Obras de restauración hidromorfológica del río... 3 81022.72 81022.72 45000000 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 1000_0005-CP01-2021-000063 EV NaN El Director General de Comunicación y Relacion... Departamento de Presidencia, Igualdad, Función... Contrato del servicio de realización de labore... 2 239797.5 47959.5 92400000 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 1379/2020 4738 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Canet de Mar Entitats municipals de Catalunya Obres de renovació de l'enllumenat públic a la... 3 214781.46 178984.55 45316100 ... https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 2021-44 EV https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Valls Entitats municipals de Catalunya Subministre i la instal·lació fotovoltaica en ... 1 129247.06 107642.2 9331000 ... https://contractaciopublica.gencat.cat/ecofin_... Enllac plec clausules tecniques.doc https://contractaciopublica.gencat.cat/ecofin_... NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
112 1005_391-2021 PUB NaN Dirección General de Cultura-Institución Prínc... Departamento de Cultura, Deporte y Juventud Apoyo a la gestión del patrimonio filmográfico... 2 104025.9 34675.3 92511000 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
113 8165_3/2021 EV NaN Mancomunidad de Servicios Sociales de Base de ... MANCOMUNIDAD DE SERVICIOS DE HUARTE Y DE ESTER... Asistencia técnica para la prestación del serv... 2 72000 14400 85000000 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
114 8113_3/2021 EV NaN Subdirector de Gestión y Recursos Agencia Navarra para la Dependencia Contrato de servicios de desinfección, desinse... 2 20305.6 4061.12 90920000 ... NaN NaN NaN 2022-01-01 2022-12-31 NaN NaN NaN NaN NaN
115 8113_01 2021 EV NaN Agencia Navarra de Autonomía y Desarrollo de l... Agencia Navarra para la Dependencia Contrato del Servicio de Teleasistencia para l... 2 11855331.61 10777574.19 [[85320000, 32500000]] ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
116 0001264/2021 RES NaN Agencia Pública Empresarial Sanitaria Bajo Gua... Junta de Andalucía 2021/pa-44-4 servicio de mantenimiento integra... 2 91979.14 19162.32 33100000 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

117 rows × 34 columns

Util

A function to produce a full index path from the upper levels. NOTE: it turns out that when loading a pd.DataFrame saved in parquet format (using to_parquet), np.nan (a float) in a multiindexed column becomes nan (a string). This is accounted for in the code below.


source

pad_col_levels

 pad_col_levels (df:pandas.core.frame.DataFrame, levels:tuple|list,
                 denan:bool=False)

Builds a multiindex-amenable column name from a sequence of levels.

Type Default Details
df DataFrame Input
levels tuple | list Individual names to assemble and pad
denan bool False If True, skip pd.NAs
Returns tuple Multiindex column name

A tuple representing column multiindex is built

col_index = pad_col_levels(hierarchical_df, ['ContractFolderStatus', 'LocatedContractingParty', 'Party', 'PartyName', 'Name'] )
col_index
('ContractFolderStatus',
 'LocatedContractingParty',
 'Party',
 'PartyName',
 'Name',
 '')

nan’s can be omitted by passing the corresponding parameter

pad_col_levels(hierarchical_df, ['ContractFolderStatus', 'LocatedContractingParty', 'Party', 'PartyName', 'Name', np.nan, np.nan], denan=True)
('ContractFolderStatus',
 'LocatedContractingParty',
 'Party',
 'PartyName',
 'Name',
 '')

It is used to retrieve the corresponding column

hierarchical_df.loc[:, col_index]
0                               Ajuntament de Sant Ramon
1                                 Pleno del Ayuntamiento
2      El Director General de Comunicación y Relacion...
3                             Ajuntament de Canet de Mar
4                                    Ajuntament de Valls
                             ...                        
112    Dirección General de Cultura-Institución Prínc...
113    Mancomunidad de Servicios Sociales de Base de ...
114                    Subdirector de Gestión y Recursos
115    Agencia Navarra de Autonomía y Desarrollo de l...
116    Agencia Pública Empresarial Sanitaria Bajo Gua...
Name: (ContractFolderStatus, LocatedContractingParty, Party, PartyName, Name, ), Length: 117, dtype: object

A function returning the columns containing a given substring in their (multi-level) name


source

columns_containing

 columns_containing (df:pandas.core.frame.DataFrame, substring:str)

Return the columns whose name contain a given substring

Type Details
df DataFrame Input
substring str Substring to be searched
columns_containing(hierarchical_df, 'Name')
MultiIndex([('ContractFolderStatus', 'LocatedContractingParty', ...),
            ('ContractFolderStatus', 'LocatedContractingParty', ...),
            ('ContractFolderStatus',      'ProcurementProject', ...),
            ('ContractFolderStatus',            'TenderResult', ...),
            ('ContractFolderStatus',         'ValidNoticeInfo', ...),
            ('ContractFolderStatus', 'LocatedContractingParty', ...)],
           )

A simple function to determine whether the columns of a pd.DataFrame are multiindexed.


source

is_column_multiindexed

 is_column_multiindexed (df:pandas.core.frame.DataFrame)

Returns True if the given pd.DataFrame is column-multiindex.

Type Details
df DataFrame Input
Returns bool Assessment
is_column_multiindexed(hierarchical_df)
True
is_column_multiindexed(df)
False

Flattening and renaming columns

The above pd.DataFrame with multiindexed columns

hier_df = flat_df_to_multiindexed_df(df)
hier_df.head(2)
id summary title updated ContractFolderStatus
ContractFolderID ContractFolderStatusCode LocatedContractingParty ProcurementProject ... LegalDocumentReference TechnicalDocumentReference ProcurementProject LocatedContractingParty TenderingProcess TenderResult
BuyerProfileURIID Party ParentLocatedParty Name ... Attachment ID Attachment PlannedPeriod Party ParentLocatedParty ParticipationRequestReceptionPeriod AwardedTenderedProject
PartyName PartyName ... ExternalReference ExternalReference StartDate EndDate PartyIdentification ParentLocatedParty EndDate EndTime ProcurementProjectLotID
Name Name ... URI URI ID PartyName
... Name
0 https://contrataciondelestado.es/sindicacion/P... Id licitación: C. 2-2021; Órgano de Contrataci... L'objecte del contracte és la renovació de tot... 2022-01-03T01:11:41.826+01:00 C. 2-2021 ADJ https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Sant Ramon Entitats municipals de Catalunya L'objecte del contracte és la renovació de tot... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 https://contrataciondelestado.es/sindicacion/P... Id licitación: 8128_3/2021; Órgano de Contrata... Obras de restauración hidromorfológica del río... 2022-01-03T01:00:11.194+01:00 8128_3/2021 PUB NaN Pleno del Ayuntamiento AYUNTAMIENTO DE MONREAL Obras de restauración hidromorfológica del río... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

2 rows × 38 columns

A mapping between columns and human-readable fields can be found here. The latter was processed in naming.ipynb to get the file below.

data_scheme_file = directory / 'PLACE.yaml'
assert data_scheme_file.exists()
data_scheme_file
PosixPath('/home/manu/Sync/UC3M/proyectos/2022/nextProcurement/sproc/samples/PLACE.yaml')

It provides (as a dict) a mapping from human-readable names to (maybe nested) fields in Atom files

with open(data_scheme_file) as yaml_data:
    data_scheme = yaml.load(yaml_data, Loader=yaml.FullLoader)
{k: data_scheme[k] for k in list(data_scheme)[:5]}
{'id': ['id', nan, nan, nan, nan, nan, nan],
 'summary': ['summary', nan, nan, nan, nan, nan, nan],
 'title': ['title', nan, nan, nan, nan, nan, nan],
 'updated': ['updated', nan, nan, nan, nan, nan, nan],
 'Número de Expediente': ['ContractFolderStatus',
  'ContractFolderID',
  nan,
  nan,
  nan,
  nan,
  nan]}

A convenience function, n2c (as in “name to column”), to go from human-readable name to actual multiindex column

n2c = lambda n: pad_col_levels(hier_df, data_scheme[n], denan=True)

The mapping can be exploited to access the columns of the pd.DataFrame using more natural names

hier_df[n2c('Número de Expediente')]
0                       C. 2-2021
1                     8128_3/2021
2      1000_0005-CP01-2021-000063
3                  1379/2020 4738
4                         2021-44
                  ...            
112                 1005_391-2021
113                   8165_3/2021
114                   8113_3/2021
115                  8113_01 2021
116                  0001264/2021
Name: (ContractFolderStatus, ContractFolderID, , , , ), Length: 117, dtype: object

A hierarchical column multiindex is assumed.

inv_data_scheme = {''.join([e if pd.notna(e) else '' for e in v]): k for k, v in data_scheme.items()}
[k for k in itertools.islice(inv_data_scheme, 4, 6)]
['ContractFolderStatusContractFolderID',
 'ContractFolderStatusContractFolderStatusCode']
('id', '', '', '', '', '') in inv_data_scheme
False
hier_df.columns.nlevels
6
''.join(hier_df.columns[0])
'id'

A tiny function to ensure some data scheme is valid


source

data_scheme_ok

 data_scheme_ok (data_scheme:dict)

Checks whether a data scheme is correct

Type Details
data_scheme dict Data scheme: every key a name, every value a path
Returns bool True if the data scheme is fine
data_scheme_ok(data_scheme)
True
import copy

A data scheme with the wrong number of elements

invalid_data_scheme = copy.deepcopy(data_scheme)
invalid_data_scheme['id'].append(np.nan)
len(invalid_data_scheme['id']), len(invalid_data_scheme['summary'])
(8, 7)
data_scheme_ok(inv_data_scheme)
True

A data scheme with the wrong type

invalid_data_scheme = copy.deepcopy(data_scheme)
invalid_data_scheme['id'].append(2)
data_scheme_ok(invalid_data_scheme)
False

A function to rename every multi-indexed column using the provided mapping (data_scheme).


source

flatten_columns_names

 flatten_columns_names (df:pandas.core.frame.DataFrame, data_scheme:dict,
                        inplace:bool=False)
Type Default Details
df DataFrame Input
data_scheme dict Every key is a flattened name, and every value a list with the different levels of the multi-index
inplace bool False If True the input DataFrame is modified
Returns None | pandas.core.frame.DataFrame Flat DataFrame
renamed_cols_df = flatten_columns_names(hier_df, data_scheme)
renamed_cols_df.head(2)
id summary title updated Número de Expediente Estado URL perfil de contratante Nombre Ubicación orgánica Objeto del Contrato ... Pliego de cláusulas administrativas (URI) Pliego de Prescripciones técnicas Pliego de Prescripciones técnicas (URI) Plazo de Ejecución (Comienzo) Plazo de Ejecución (Fin) ID ContractFolderStatus - LocatedContractingParty - ParentLocatedParty - ParentLocatedParty - PartyName - Name Presentación de Solicitudes (Fecha) Presentación de Solicitudes (Hora) Lote
0 https://contrataciondelestado.es/sindicacion/P... Id licitación: C. 2-2021; Órgano de Contrataci... L'objecte del contracte és la renovació de tot... 2022-01-03T01:11:41.826+01:00 C. 2-2021 ADJ https://contractaciopublica.gencat.cat/ecofin_... Ajuntament de Sant Ramon Entitats municipals de Catalunya L'objecte del contracte és la renovació de tot... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 https://contrataciondelestado.es/sindicacion/P... Id licitación: 8128_3/2021; Órgano de Contrata... Obras de restauración hidromorfológica del río... 2022-01-03T01:00:11.194+01:00 8128_3/2021 PUB NaN Pleno del Ayuntamiento AYUNTAMIENTO DE MONREAL Obras de restauración hidromorfológica del río... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

2 rows × 38 columns

One can now used the human-readable columns names, e.g.

renamed_cols_df['Número de Expediente']
0                       C. 2-2021
1                     8128_3/2021
2      1000_0005-CP01-2021-000063
3                  1379/2020 4738
4                         2021-44
                  ...            
112                 1005_391-2021
113                   8165_3/2021
114                   8113_3/2021
115                  8113_01 2021
116                  0001264/2021
Name: Número de Expediente, Length: 117, dtype: object

Insiders & Minors

The data scheme for both

data_scheme_file = directory.parent / 'naming' / 'insiders_minors.yaml'
print(data_scheme_file)
assert data_scheme_file.exists()
/home/manu/Sync/UC3M/proyectos/2022/nextProcurement/sproc/naming/insiders_minors.yaml
with open(data_scheme_file) as yaml_data:
    data_scheme = yaml.load(yaml_data, Loader=yaml.FullLoader)
{k: data_scheme[k] for k in list(data_scheme)[:5]}
{'id': ['id'],
 'summary': ['summary'],
 'title': ['title'],
 'updated': ['updated'],
 'deleted_on': ['deleted_on']}
Insiders
insiders_file = directory / 'insiders_sample.parquet'
print(insiders_file)
assert insiders_file.exists()
/home/manu/Sync/UC3M/proyectos/2022/nextProcurement/sproc/samples/insiders_sample.parquet
insiders_df = pd.read_parquet(insiders_file)
insiders_df
id summary title updated ContractFolderStatus deleted_on
ContractFolderID ContractFolderStatusCode LocatedContractingParty ... TenderingTerms ProcurementProjectLot LocatedContractingParty TendererStatus TenderResult TenderingTerms LocatedContractingParty
ContractingPartyTypeCode Party ... TendererQualificationRequest TenderingTerms ParentLocatedParty ProcurementProjectLotID WinningParty ProcurementNationalLegislationCode TendererQualificationRequest ParentLocatedParty
PartyIdentification PartyName PostalAddress ... EmployeeQuantityDescription TendererQualificationRequest ParentLocatedParty PartyLegalEntity OperatingYearsDescription ParentLocatedParty
ID Name CityName ... SpecificTendererRequirement ParentLocatedParty CompanyTypeCode ParentLocatedParty
... RequirementTypeCode Description ParentLocatedParty ParentLocatedParty
... ParentLocatedParty ParentLocatedParty
... ParentLocatedParty ParentLocatedParty
... PartyIdentification ParentLocatedParty
... ID PartyIdentification
... ID
...
zip file name entry
licitacionesPerfilesContratanteCompleto3_2018.zip licitacionesPerfilesContratanteCompleto3_20200522_234632_1.atom 494 https://contrataciondelestado.es/sindicacion/l... Id licitación: LICT/99/024/2017/0063; Órgano d... Contratación de la Obra de creación de un nuev... 2017-12-29 12:36:06.402000+00:00 LICT/99/024/2017/0063 RES 5.0 [G28207017] Director Gerente de FREMAP Majadahonda (Madrid) ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
489 https://contrataciondelestado.es/sindicacion/l... Id licitación: 357/17; Órgano de Contratación:... Suministro de mobiliario Hospital de Sagunt 2017-12-29 12:44:12.934000+00:00 357/17 ADJ 2.0 [S4611001A] Departamento de Salud de Sagunto. Dirección Ec... Sagunto ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
488 https://contrataciondelestado.es/sindicacion/l... Id licitación: 7.1.23/17; Órgano de Contrataci... Red separativa de alcantarillado en el barrio ... 2017-12-29 12:45:04.741000+00:00 7.1.23/17 RES 2.0 [S3933002B] Consejería de Universidades e Investigación, M... Santander ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
486 https://contrataciondelestado.es/sindicacion/l... Id licitación: 5/2016; Órgano de Contratación:... Prestación del servicio de vigilancia y limpie... 2017-12-29 12:45:20.094000+00:00 5/2016 RES 3.0 [L01120271, P1202700I] Teniente de Alcalde Delegado del Área de Contr... Benicarló ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
481 https://contrataciondelestado.es/sindicacion/l... Id licitación: 1004217003400; Órgano de Contra... Servicios de mantenimiento y desarrollo de los... 2017-12-29 12:48:25.547000+00:00 1004217003400 RES 1.0 [E00116302, S2800643E] Jefatura de la Sección Económico Financiera de... Madrid ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT

5 rows × 195 columns

flatten_columns_names(insiders_df, data_scheme)
id summary title updated Número de Expediente (Datos Generales del Expediente) Estado (Datos Generales del Expediente) Tipo de Administración (Entidad Adjudicadora) ID (Entidad Adjudicadora) Nombre (Entidad Adjudicadora) Población (Entidad Adjudicadora) ... Empleados (descripción) (Requisitos de Participación) Condiciones de admisión (código) (Requisitos de Participación del Lote) Condiciones de admisión (Requisitos de Participación del Lote) Ubicación orgánica ID (6) (Entidad Adjudicadora Jerarquía) ContractFolderStatus_TendererStatus_ProcurementProjectLotID (Unmatched) El adjudicatario es una UTE (Adjudicatario) ContractFolderStatus_TenderingTerms_ProcurementNationalLegislationCode (Unmatched) Experiencia (descripción) (Requisitos de Participación) Ubicación orgánica ID (7) (Entidad Adjudicadora Jerarquía) deleted_on
zip file name entry
licitacionesPerfilesContratanteCompleto3_2018.zip licitacionesPerfilesContratanteCompleto3_20200522_234632_1.atom 494 https://contrataciondelestado.es/sindicacion/l... Id licitación: LICT/99/024/2017/0063; Órgano d... Contratación de la Obra de creación de un nuev... 2017-12-29 12:36:06.402000+00:00 LICT/99/024/2017/0063 RES 5.0 [G28207017] Director Gerente de FREMAP Majadahonda (Madrid) ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
489 https://contrataciondelestado.es/sindicacion/l... Id licitación: 357/17; Órgano de Contratación:... Suministro de mobiliario Hospital de Sagunt 2017-12-29 12:44:12.934000+00:00 357/17 ADJ 2.0 [S4611001A] Departamento de Salud de Sagunto. Dirección Ec... Sagunto ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
488 https://contrataciondelestado.es/sindicacion/l... Id licitación: 7.1.23/17; Órgano de Contrataci... Red separativa de alcantarillado en el barrio ... 2017-12-29 12:45:04.741000+00:00 7.1.23/17 RES 2.0 [S3933002B] Consejería de Universidades e Investigación, M... Santander ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
486 https://contrataciondelestado.es/sindicacion/l... Id licitación: 5/2016; Órgano de Contratación:... Prestación del servicio de vigilancia y limpie... 2017-12-29 12:45:20.094000+00:00 5/2016 RES 3.0 [L01120271, P1202700I] Teniente de Alcalde Delegado del Área de Contr... Benicarló ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT
481 https://contrataciondelestado.es/sindicacion/l... Id licitación: 1004217003400; Órgano de Contra... Servicios de mantenimiento y desarrollo de los... 2017-12-29 12:48:25.547000+00:00 1004217003400 RES 1.0 [E00116302, S2800643E] Jefatura de la Sección Económico Financiera de... Madrid ... <NA> [nan] [nan] <NA> [nan] [nan] <NA> <NA> <NA> NaT

5 rows × 195 columns

Minors
minors_file = directory / 'minors_sample.parquet'
assert minors_file.exists()
print(minors_file)
/home/manu/Sync/UC3M/proyectos/2022/nextProcurement/sproc/samples/minors_sample.parquet
minors_df = pd.read_parquet(minors_file)
minors_df
id summary title updated ContractFolderStatus deleted_on
ContractFolderID ContractFolderStatusCode LocatedContractingParty ProcurementProject ... TenderResult TendererStatus TenderResult LocatedContractingParty TenderingTerms LocatedContractingParty
Party Name TypeCode ... WinningParty ProcurementProjectLotID WinningParty ParentLocatedParty FundingProgramCode FundingProgram ParentLocatedParty
PartyIdentification PartyName ... PhysicalLocation PartyLegalEntity ParentLocatedParty ParentLocatedParty
ID Name ... Address CompanyTypeCode ParentLocatedParty ParentLocatedParty
... PostalZone ParentLocatedParty ParentLocatedParty
... ParentLocatedParty ParentLocatedParty
... PartyIdentification ParentLocatedParty ParentLocatedParty
... ID PartyIdentification ParentLocatedParty
... ID PartyIdentification ParentLocatedParty
... ID PartyName
... Name
zip file name entry
contratosMenoresPerfilesContratantes_2018.zip contratosMenoresPerfilesContratantes_20190225_140722_12.atom 499 https://contrataciondelestado.es/sindicacion/d... Id licitación: 000103/2017-1069; Órgano de Con... Reforma de elementos de ventilación exterior d... 2018-01-02 07:41:12.989000+00:00 000103/2017-1069 RES [L01300275] Junta de Gobierno del Ayuntamiento de Molina d... Reforma de elementos de ventilación exterior d... 2.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
498 https://contrataciondelestado.es/sindicacion/d... Id licitación: 29-2017-II; Órgano de Contratac... Servicios de calibrado y certificado de dos de... 2018-01-02 07:48:40.056000+00:00 29-2017-II RES [E04803403] Presidencia de la Confederación Hidrográfica d... Servicios de calibrado y certificado de dos de... 2.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
497 https://contrataciondelestado.es/sindicacion/d... Id licitación: 013-07-2018; Órgano de Contrata... Patrocinio menor proyecto " Activitats C.I.N.E" 2018-01-02 07:52:03.763000+00:00 013-07-2018 RES [A04013514] Agencia de Turismo de las Illes Balears Patrocinio menor proyecto " Activitats C.I.N.E" 8.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
496 https://contrataciondelestado.es/sindicacion/d... Id licitación: CON/2017/51; Órgano de Contrata... Redacción EPIA - Legalización antena emisora d... 2018-01-02 07:53:43.525000+00:00 CON/2017/51 RES [L01330117] Alcaldía del Ayuntamiento de Cangas del Narcea Redacción EPIA - Legalización antena emisora d... 2.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
495 https://contrataciondelestado.es/sindicacion/d... Id licitación: 000047/2017-1069; Órgano de Con... Obras de reparación del Centro de Información ... 2018-01-02 08:14:33.726000+00:00 000047/2017-1069 RES [L01300275] Junta de Gobierno del Ayuntamiento de Molina d... Obras de reparación del Centro de Información ... 3.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT

5 rows × 107 columns

flatten_columns_names(minors_df, data_scheme)
id summary title updated Número de Expediente (Datos Generales del Expediente) Estado (Datos Generales del Expediente) ID (Entidad Adjudicadora) Nombre (Entidad Adjudicadora) Objeto del Contrato (Datos Generales del Expediente) Tipo de Contrato (Datos Generales del Expediente) ... Código Postal (Adjudicatario) ContractFolderStatus_TendererStatus_ProcurementProjectLotID (Unmatched) El adjudicatario es una UTE (Adjudicatario) Ubicación orgánica ID (5) (Entidad Adjudicadora Jerarquía) Ubicación orgánica ID (6) (Entidad Adjudicadora Jerarquía) Descripción de Programas de Financiación (Condiciones de Licitación) Programas de Financiación (Condiciones de Licitación) Ubicación orgánica ID (7) (Entidad Adjudicadora Jerarquía) Ubicación orgánica (8) (Entidad Adjudicadora Jerarquía) deleted_on
zip file name entry
contratosMenoresPerfilesContratantes_2018.zip contratosMenoresPerfilesContratantes_20190225_140722_12.atom 499 https://contrataciondelestado.es/sindicacion/d... Id licitación: 000103/2017-1069; Órgano de Con... Reforma de elementos de ventilación exterior d... 2018-01-02 07:41:12.989000+00:00 000103/2017-1069 RES [L01300275] Junta de Gobierno del Ayuntamiento de Molina d... Reforma de elementos de ventilación exterior d... 2.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
498 https://contrataciondelestado.es/sindicacion/d... Id licitación: 29-2017-II; Órgano de Contratac... Servicios de calibrado y certificado de dos de... 2018-01-02 07:48:40.056000+00:00 29-2017-II RES [E04803403] Presidencia de la Confederación Hidrográfica d... Servicios de calibrado y certificado de dos de... 2.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
497 https://contrataciondelestado.es/sindicacion/d... Id licitación: 013-07-2018; Órgano de Contrata... Patrocinio menor proyecto " Activitats C.I.N.E" 2018-01-02 07:52:03.763000+00:00 013-07-2018 RES [A04013514] Agencia de Turismo de las Illes Balears Patrocinio menor proyecto " Activitats C.I.N.E" 8.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
496 https://contrataciondelestado.es/sindicacion/d... Id licitación: CON/2017/51; Órgano de Contrata... Redacción EPIA - Legalización antena emisora d... 2018-01-02 07:53:43.525000+00:00 CON/2017/51 RES [L01330117] Alcaldía del Ayuntamiento de Cangas del Narcea Redacción EPIA - Legalización antena emisora d... 2.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT
495 https://contrataciondelestado.es/sindicacion/d... Id licitación: 000047/2017-1069; Órgano de Con... Obras de reparación del Centro de Información ... 2018-01-02 08:14:33.726000+00:00 000047/2017-1069 RES [L01300275] Junta de Gobierno del Ayuntamiento de Molina d... Obras de reparación del Centro de Información ... 3.0 ... [nan] [nan] NaN <NA> <NA> [nan] <NA> <NA> <NA> NaT

5 rows × 107 columns