簡體   English   中英

在Python中展平實體-屬性-值(EAV)架構

[英]Flatten Entity-Attribute-Value (EAV) Schema in Python

我有一個實體屬性值格式的csv文件( ,我的event_id是非唯一的,並且對k個相關屬性重復了k次):

    event_id, attribute_id, value
    1, 1, a
    1, 2, b
    1, 3, c
    2, 1, a
    2, 2, b
    2, 3, c
    2, 4, d

是否有任何方便的技巧將可變數量的屬性( 行)轉換為列? 這里的關鍵是輸出應該是結構化數據的mxn表,其中m = max(k) ; NULL填充缺少的屬性將是最佳選擇:

    event_id, 1, 2, 3, 4
    1, a, b, c, null
    2, a, b, c, d

我的計划是(1)將csv轉換為如下所示的JSON對象:

    data = [{'value': 'a', 'id': '1', 'event_id': '1', 'attribute_id': '1'},
     {'value': 'b', 'id': '2', 'event_id': '1', 'attribute_id': '2'},
     {'value': 'a', 'id': '3', 'event_id': '2', 'attribute_id': '1'},
     {'value': 'b', 'id': '4', 'event_id': '2', 'attribute_id': '2'},
     {'value': 'c', 'id': '5', 'event_id': '2', 'attribute_id': '3'},
     {'value': 'd', 'id': '6', 'event_id': '2', 'attribute_id': '4'}]

(2)提取唯一的事件ID:

    events = set()
    for item in data:
        events.add(item['event_id'])

(3)創建一個列表列表,其中每個內部列表都是相應父事件的屬性列表。

    attributes = [[k['value'] for k in j] for i, j in groupby(data, key=lambda x: x['event_id'])]

(4)創建將事件和屬性放在一起的字典:

    event_dict = dict(zip(events, attributes))

看起來像這樣:

    {'1': ['a', 'b'], '2': ['a', 'b', 'c', 'd']}

我不確定如何使所有內部列表的長度相同,並在必要時填充NULL值。 似乎需要在步驟(3)中完成某些操作。 另外,我已經想到創建n個充滿m個 NULL值的列表,然后遍歷每個列表並使用attribute_id作為列表位置填充該值; 但這看起來很簡陋。

您的基本想法似乎是正確的,盡管我可以按以下方式實現它:

import itertools
import csv

events = {}  # we're going to keep track of the events we read in
with open('path/to/input') as infile:
    for event, _att, val in csv.reader(infile):
        if event not in events:
            events[event] = []
        events[int(event)].append(val)  # track all the values for this event

maxAtts = max(len(v) for _k,v in events.items())  # the maximum number of attributes for any event
with open('path/to/output', 'w') as outfile):
    writer = csv.writer(outfile)
    writer.writerow(["event_id"] + list(range(1, maxAtts+1)))  # write out the header row
    for k in sorted(events):  # let's look at the events in sorted order
        writer.writerow([k] + events[k] + ['null']*(maxAtts-len(events[k])))  # write out the event id, all the values for that event, and pad with "null" for any attributes without values

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM