[FIXED] Flattern von verschachteltem JSON und Retain-Spalten (oder Panda json_normalize)

Ausgabe

Ich habe einen Json mit einigen verschachtelten/Array-Elementen wie dem folgenden, den ich gerade glätte, bevor ich ihn in einer CSV-Datei speichere

{'SKU':'TEST1','name':'test name 1',
    'ItemSalesPrices':[{'SourceNumber': 'OEM', 'AssetNumber': 'TEST1', 'UnitPrice': 1600}, {'SourceNumber': 'RRP', 'AssetNumber': 'TEST1', 'UnitPrice': 1500}],
    'ItemDiscounts':[{'SourceNumber': 'RETAIL', 'AssetNumber': 'AC', 'LineDiscountPercentage': 30}, {'SourceNumber': 'LARGE ACC', 'AssetNumber': 'AC', 'LineDiscountPercentage': 45}]
    },
{'SKU':'TEST2','name':'test name 2',
    'ItemSalesPrices':[{'SourceNumber': 'RRP', 'AssetNumber': 'TEST2', 'UnitPrice': 1500}],
    'ItemDiscounts':[{'SourceNumber': 'RETAIL', 'AssetNumber': 'AC', 'LineDiscountPercentage': 30}]
    }

Ich hoffe, es in mehr Spalten zu reduzieren. Wenn ich es also in CSV speichere, hat es immer noch 2 Zeilen mit Spalten, die die einzelnen Source NUMber-Elemente in jedem Array darstellen.

Artikelnummer Name ItemSalesPrices_OEM ItemSalesPrices_UVP ItemDiscounts_Retail ItemDiscounts_LARGE ACC
TEST1 Prüfungsname 1 1600 1500 30 45
TEST2 Prüfungsname 2 1500 30

Im Moment gehe ich jedes Element durch, durchlaufe das Array und führe alle Arten von Überprüfungen und Vergleichen mit der SourceNumber durch

Ich glaube nicht, dass ich auf dem richtigen Weg bin und hoffe, von euch zu hören, um zu sehen, wie dies angegangen werden sollte

Vielen Dank

Lösung

Verwenden Sie json_normalizemit DataFrame.pivotoder DataFrame.pivot_tableund treten Sie dann DataFrames bei, indem Sie concat:

data = [{'SKU':'TEST1','name':'test name 1',
    'ItemSalesPrices':[{'SourceNumber': 'OEM', 'AssetNumber': 'TEST1', 'UnitPrice': 1600}, 
                       {'SourceNumber': 'RRP', 'AssetNumber': 'TEST1', 'UnitPrice': 1500}],
    'ItemDiscounts':[{'SourceNumber': 'RETAIL', 'AssetNumber': 'AC', 'LineDiscountPercentage': 30},
                     {'SourceNumber': 'LARGE ACC', 'AssetNumber': 'AC', 'LineDiscountPercentage': 45}]
    },
{'SKU':'TEST2','name':'test name 2',
    'ItemSalesPrices':[{'SourceNumber': 'RRP', 'AssetNumber': 'TEST2', 'UnitPrice': 1500}],
    'ItemDiscounts':[{'SourceNumber': 'RETAIL', 'AssetNumber': 'AC', 'LineDiscountPercentage': 30}]
    }]

first = ['SKU','name']
df1 = (pd.json_normalize(data,'ItemSalesPrices', first)
        .pivot_table(index=first, 
                     columns='SourceNumber', 
                     values='UnitPrice', 
                     aggfunc='sum')
        .add_prefix('ItemSalesPrices_'))
df2 = (pd.json_normalize(data,'ItemDiscounts', first)
        .pivot_table(index=first, 
                     columns='SourceNumber', 
                     values='LineDiscountPercentage', 
                     aggfunc='sum')
        .add_prefix('ItemSalesPrices_'))      
        
        
df3 = pd.concat([df1, df2], axis=1).rename_axis(None, axis=1).reset_index()
print (df3)
     SKU         name  ItemSalesPrices_OEM  ItemSalesPrices_RRP  \
0  TEST1  test name 1               1600.0               1500.0   
1  TEST2  test name 2                  NaN               1500.0   

   ItemSalesPrices_LARGE ACC  ItemSalesPrices_RETAIL  
0                       45.0                    30.0  
1                        NaN                    30.0  

Wenn keine Duplikate hier sind, ist eine alternative Lösung:

from collections import defaultdict

d = defaultdict(dict)

for x in data:
    for y in x['ItemSalesPrices']:
        d['ItemSalesPrices_' + y['SourceNumber']].update({(x['SKU'], x['name']):y['UnitPrice']})
    for y in x['ItemDiscounts']:
        d['ItemDiscounts_' + y['SourceNumber']].update({(x['SKU'], x['name']):y['LineDiscountPercentage']})

df = pd.DataFrame(d).rename_axis(['SKU','name']).reset_index()
print(df)
     SKU         name  ItemSalesPrices_OEM  ItemSalesPrices_RRP  \
0  TEST1  test name 1               1600.0                 1500   
1  TEST2  test name 2                  NaN                 1500   

   ItemDiscounts_RETAIL  ItemDiscounts_LARGE ACC  
0                    30                     45.0  
1                    30                      NaN  


Beantwortet von –
jezrael


Antwort geprüft von –
Jay B. (FixError Admin)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like