ArneBinder's picture
update from https://github.com/ArneBinder/argumentation-structure-identification/pull/529
d868d2e verified
import json
from typing import Dict, List, Optional, Tuple
import pandas as pd
def parse_identifier(
identifier_str, defaults: Dict[str, str], parts_sep: str = ",", key_val_sep: str = "="
) -> Dict[str, str]:
parts = [
part.split(key_val_sep)
for part in identifier_str.strip().split(parts_sep)
if key_val_sep in part
]
parts_dict = dict(parts)
return {**defaults, **parts_dict}
def read_nested_json(path: str) -> pd.DataFrame:
# Read the nested JSON data into a pandas DataFrame
with open(path, "r") as f:
data = json.load(f)
result = pd.json_normalize(data, sep="/")
result.index.name = "entry"
return result
def read_nested_jsons(
json_paths: List[Tuple[str, str]],
default_key_values: Optional[Dict[str, str]] = None,
column_level_names: Optional[List[str]] = None,
) -> pd.DataFrame:
dfs = [read_nested_json(json_path) for identifier_str, json_path in json_paths]
new_index_levels = pd.MultiIndex.from_frame(
pd.DataFrame(
[
parse_identifier(identifier_str, default_key_values or {})
for identifier_str, _ in json_paths
]
)
)
if len(set(list(new_index_levels))) == len(list(new_index_levels)):
dfs_concat = pd.concat(
dfs, keys=list(new_index_levels), names=new_index_levels.names, axis=0
)
else:
dfs_new = []
ids_unique = []
for identifier_str in new_index_levels:
if identifier_str not in ids_unique:
ids_unique.append(identifier_str)
# first combine the dataframes with same ids along the columns
for identifier_str in ids_unique:
dfs_with_id = [df for df, idx in zip(dfs, new_index_levels) if idx == identifier_str]
# assert that all columns are distinct
if len(set([tuple(col) for df in dfs_with_id for col in df.columns])) != sum(
[len(df.columns) for df in dfs_with_id]
):
raise ValueError(
"There are duplicate columns across the dataframes with the same identifier."
)
dfs_id_concat = pd.concat(dfs_with_id, axis=1)
dfs_new.append(dfs_id_concat)
dfs_concat = pd.concat(dfs_new, keys=ids_unique, names=new_index_levels.names, axis=0)
dfs_concat.columns = pd.MultiIndex.from_tuples(
[col.split("/") for col in dfs_concat.columns], names=column_level_names
)
return dfs_concat