Mam ramkę danych jak poniżej:

 df.head(2)

Ord MOT  MVT  CUST  CreationSla  CreationPlanned CreationProposed  PickupSla  PickupPlanned PickupProposed
 12  TR    TT   DEA  12-3-2020      12-3-2020      12-3-2020       14-3-2020   14-3-2020    14-3-2020
 15  ZR    TD   DET  15-3-2020      15-3-2020      15-3-2020       16-3-2020   16-3-2020    16-3-2020

Chcę utworzyć zagnieżdżony plik JSON w poniższym formacie:

Oczekiwany wynik

{
    "Ord" : "12",
    "MOT" : "TR",
    "MVT" : "TT",
    "CUST" : "DEA",
    "milestone" : {
        "creation" : {
            "sla" : "12-3-2020",
            "plan" : "12-3-2020",
            "proposed" : "12-3-2020"
        },
        "Pickup" : {
            "sla" : "14-3-2020",
            "plan" : "14-3-2020",
            "proposed" : "14-3-2020"
        }
    }
}

Jak można to zrobić w Pythonie?

3
Rahul rajan 1 kwiecień 2020, 05:08

3 odpowiedzi

Najlepsza odpowiedź

Po pierwsze, będziesz musiał zapętlić wiersze swojej ramki danych.

Następnie z każdym wierszem tworzysz słownik. Cały pomysł jest taki:

result = []
predefined_columns = ['Creation', 'Pickup', 'Departure']
mapping_cl = []
for column in df.columns:
    flag = False
    for sub_str in predefined_columns:
        if sub_str in column:
            flag = True
            mapping_cl.append(sub_str)
            break
    if not flag:
        mapping_cl.append(False)
for index, row in df.iterrows():
    item = {}
    for cl in mapping_cl:
        if cl:
            item[cl] = {}
    for i, column in enumerate(df.columns):
        if mapping_cl[i]:
            cl_name = column.split(mapping_cl[i])[-1]
            item[mapping_cl[i]][cl_name] = row[column]
        else:
            item[column] = row[column]
    result.append(item)

Teraz result to lista dict, jak chcesz:

Enter image description here

1
Peter Mortensen 23 sierpień 2020, 23:14

Możesz stworzyć szablon JSON i przesłać do niego dane:

d = """{
    "Ord" : "%s",
    "MOT" : "%s",
    "MVT" : "%s",
    "CUST" : "%s",
    "milestone" : {
        "creation" : {
            "sla" : "%s",
            "plan" : "%s",
            "proposed" : "%s"
        },
        "Pickup" : {
            "sla" : "%s",
            "plan" : "%s",
            "proposed" : "%s"
        }
    }
}
"""
js = []

for item in df.values:
    js.append(json.loads(d%tuple(item.tolist())))

print(json.dumps(js))

Wynik:

[{"Ord": "a", "MOT": "TR", "MVT": "TT", "CUST": "DEA", "milestone": {"creation": {"sla": "12-3-2020", "plan": "12-3-2020", "proposed": "12-3-2020"}, "Pickup": {"sla": "14-3-2020", "plan": "14-3-2020", "proposed": "14-3-2020"}}}, {"Ord": "b", "MOT": "ZR", "MVT": "TD", "CUST": "DET", "milestone": {"creation": {"sla": "15-3-2020", "plan": "15-3-2020", "proposed": "15-3-2020"}, "Pickup": {"sla": "16-3-2020", "plan": "16-3-2020", "proposed": "16-3-2020"}}}]
4
Peter Mortensen 1 kwiecień 2020, 16:42

Ponieważ wspomniałeś o Pandach, używam wide_to_long, a następnie groupby do tworzenia Twojego formatu. Zwróć uwagę, że wymaga to zmiany level w przypadku zmiany formatu danych.

s=pd.wide_to_long(df,stubnames=['Creation','Pickup'],i=['Ord', 'MOT', 'MVT', 'CUST'],j='type' , suffix='\w+').stack().unstack(level=-2)
js=[{**dict(zip(s.index.names[:-1],x)),**{'milestone' : y.reset_index(level=[0,1,2,3],drop=True).to_dict('i') }} for x , y in s.groupby(level=[0,1,2,3])]
js
[{'Ord': 12, 'MOT': 'TR', 'MVT': 'TT', 'CUST': 'DEA',
 'milestone':
  {'Creation':
  {'Planned': '12-3-2020', 'Proposed': '12-3-2020', 'Sla': '12-3-2020'}, 'Pickup': {'Planned': '14-3-2020', 'Proposed': '14-3-2020', 'Sla': '14-3-2020'}}},
 {'Ord': 15, 'MOT': 'ZR', 'MVT': 'TD', 'CUST': 'DET',
  'milestone':
  {'Creation':
  {'Planned': '15-3-2020', 'Proposed': '15-3-2020', 'Sla': '15-3-2020'}, 'Pickup': {'Planned': '16-3-2020', 'Proposed': '16-3-2020', 'Sla': '16-3-2020'}}}]
4
Peter Mortensen 1 kwiecień 2020, 16:44