【问题标题】:Dynamically explode list columns in PandasPandas 中的动态分解列表列
【发布时间】:2021-05-22 07:48:53
【问题描述】:

我有一个已使用 json_normalize 转换为数据框的字典列表。

数据集:

x = [{ 
    "_id" : 71, 
    "Ids" : [
        "10", 
        "59"
    ], 
    "roles" : [
        "janitor", "mechanic", "technician"
    ]
}]

数据框:

   _id       Ids                            roles
    71  [10, 59]  [janitor, mechanic, technician]

我正在尝试做的是找到一种方法来动态分解所有列表列/键(ID 和角色),而无需显式输入列名。这可能吗?

所需的输出:

   _id       Ids         roles
    71        10       janitor
    71        10      mechanic
    71        10    technician
    71        59       janitor
    71        59      mechanic
    71        59    technician

任何帮助将不胜感激。

【问题讨论】:

    标签: python pandas list dynamic


    【解决方案1】:

    我不确定这样做的效率,但它只是遍历数据框列名并检查它是否为list。如果是list 就只是explode

    df_final = df.copy()
    
    for c in df.columns:
        if(isinstance(df[c][0],list)):
            df_final = df_final.explode(c)
    
        _id Ids roles
    0   71  10  janitor
    0   71  10  mechanic
    0   71  10  technician
    0   71  59  janitor
    0   71  59  mechanic
    0   71  59  technician
    
    

    【讨论】:

      【解决方案2】:

      我会这样做:

      from itertools import product
      
      list_ = [df.iloc[0,i] if type(df.iloc[0,i]) == list else [df.iloc[0,i]] for i in range(df.shape[1])]
      prod = list(product(*list_))
      df = pd.DataFrame(prod, columns=df.columns)
      

      【讨论】:

      • 我假设因为有一些方法可以在不导入任何内容的情况下进行,df.iloc[0,2] 假设有第三列,它应该是完全动态的,因为代码应该检查是否column 包含一个列表,因此不应假设总是有 3 列,因为它每次都会变化
      • @mdbuzzer 感谢您的评论,现在您可以独立于列数了
      【解决方案3】:

      遍历所有条目以检查列表的简单解决方案。

      适用于多行条目和嵌套列表。

          while True:
              newdf = pd.DataFrame(columns=df.columns)
              for row in df.values:
                  for index, value in enumerate(row):
                      if isinstance(value, list):
                          for listentry in value:
                              newdf.loc[len(newdf)] = [*row[:index], listentry, *row[index+1:]] 
                          break
                  else:
                      newdf.loc[len(newdf)] = row
              df = newdf.copy(deep=True)
              if not newdf.applymap(lambda value:isinstance(value, list)).values.any():
                  break
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-30
        • 2017-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-23
        相关资源
        最近更新 更多