【问题标题】:How to transform a complicated list to dataframe in Python如何在 Python 中将复杂的列表转换为数据框
【发布时间】:2021-02-21 13:25:29
【问题描述】:

我有这样的清单

[9308, '127.05', [{'id': 8568, 'name': 'some product name', 'product_id': 4204, 'variation_id': 0, 'quantity': 1, 'tax_class': '', 'subtotal': '139.00', 'subtotal_tax': '0.00', 'total': '118.15', 'total_tax': '0.00', 'taxes': [], 'meta_data': [], 'sku': '', 'price': 118.15}], 9306, '98.89', [{'id': 8566, 'name': 'some product name', 'product_id': 4200, 'variation_id': 0, 'quantity': 1, 'tax_class': '', 'subtotal': '89.99', 'subtotal_tax': '0.00', 'total': '89.99', 'total_tax': '0.00', 'taxes': [], 'meta_data': [], 'sku': '', 'price': 89.99}]

我想将其转换为如下所示的数据框:

ID   Total Value     Product IDs
9308   127.05        4204
9306   98.89         4200
etc.

还有一些 ID 可能只有很少的产品 ID,因此列表应如下所示:

ID   Total Value     Product IDs
9308   127.05        4204
9308   127.05        4200
9308   127.05        5555

谁能帮助我?我是 Python 的初学者。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    IIUC,而且你的输入列表结构真的很好,那么你可以像这样使用一些硬编码:

    df_out = pd.concat([pd.DataFrame(l[::3], columns=['ID']), 
                        pd.DataFrame(l[1::3], columns=['Total Value']), 
                        pd.concat([pd.DataFrame(i) for i in l[2::3]], ignore_index=True)
                          .loc[:, 'product_id']], axis=1)
    

    输出:

         ID Total Value  product_id
    0  9308      127.05        4204
    1  9306       98.89        4200
    

    【讨论】:

    • 在您的情况下,ID 只需要第一个 product_id。正如我所说,一个 ID 可以有多个产品 ID
    【解决方案2】:

    您可以使用itertools 中的grouper 配方轻松完成此操作。 https://docs.python.org/3/library/itertools.html#itertools-recipes

    # Copied from itertools recipes link above
    from itertools import zip_longest
    
    def grouper(iterable, n, fillvalue=None):
        "Collect data into fixed-length chunks or blocks"
        # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
        args = [iter(iterable)] * n
        return zip_longest(*args, fillvalue=fillvalue)
    

    然后您使用它以 3 块为单位遍历数据,并将其组合成 defaultdict 以将您的数据构建为 DataFrame 的正确格式

    import collections
    
    clean_data = collections.defaultdict(list)
    
    for entry_id, total_value, product_json in grouper(data, 3):
        for record in product_json:
            clean_data["id"].append(entry_id)
            clean_data["total_value"].append(total_value)
            clean_data["product_id"].append(record["product_id"])
        
    df = pd.DataFrame(clean_data)
    print(df)
         id total_value  product_id
    0  9308      127.05        4204
    1  9306       98.89        4200
    

    这也将处理您在第三个数据中有超过 1 条记录的情况(例如,如果您的列表中有 2 个字典,而不是只有 1 个)

    【讨论】:

      【解决方案3】:

      假设数组的结构是ID、总值和产品信息,编码为json。如果我们一次遍历该数组三个项目,那么下面应该可以正常工作:

      def unzip(i,v,d):
          return pd.DataFrame(d).assign(ID=i, TotalValue=v )
      df = pd.concat([unzip(i,v,d) for i, v, d in zip(*[iter(js)]*3)])
      df[['ID','TotalValue', 'product_id']]
      

      示例输出:

      注意事项:有关如何iterate multiple items at a time 的详细信息。 使用 json 时,我发现先创建一个数据框,然后添加广播到所有数据框行的其他列更容易。

      假设:输入字符串缺少关闭“]”,否则它不是数组。上面的代码适用于这个输入。

      js = [ 9308, '127.05', [{'id': 8568, 'name': 'some product name', 'product_id': 4204, 'variation_id': 0, 'quantity': 1, 'tax_class': '', 'subtotal': '139.00', 'subtotal_tax': '0.00', 'total': '118.15', 'total_tax': '0.00', 'taxes': [], 'meta_data': [], 'sku': '', 'price': 118.15}], 
              9306, '98.89',  [{'id': 8566, 'name': 'some product name', 'product_id': 4200, 'variation_id': 0, 'quantity': 1, 'tax_class': '', 'subtotal': '89.99', 'subtotal_tax': '0.00', 'total': '89.99', 'total_tax': '0.00', 'taxes': [], 'meta_data': [], 'sku': '', 'price': 89.99}]]
      

      【讨论】:

      • 对不起,它不起作用。它需要第一个 id(例如:[{'id': 8568)而不是 product_id
      • 它正在复制您的预期结果。您能否提供一个不起作用的示例输入?
      猜你喜欢
      • 1970-01-01
      • 2013-07-26
      • 2018-10-30
      • 2021-10-16
      • 2023-01-26
      • 1970-01-01
      • 2013-01-27
      • 1970-01-01
      相关资源
      最近更新 更多