【问题标题】:What's the best way to create a Pandas MultiIndex from a list of dictionaries?从字典列表创建 Pandas MultiIndex 的最佳方法是什么?
【发布时间】:2019-06-11 03:22:12
【问题描述】:

我有一个迭代过程,每次迭代都使用不同的参数值运行,我想收集参数值和结果并将它们放入 Pandas 数据框中,该数据框具有从参数值集(唯一)构建的多索引.

每次迭代,参数值都在字典中,如下所示:

params = {'p': 2, 'q': 7}

因此很容易将它们与结果一起收集到一个列表中:

results_index = [
    {'p': 2, 'q': 7},
    {'p': 2, 'q': 5},
    {'p': 1, 'q': 4},
    {'p': 2, 'q': 4}
]
results_data = [
    {'A': 0.18, 'B': 0.18},
    {'A': 0.67, 'B': 0.21},
    {'A': 0.96, 'B': 0.45},
    {'A': 0.58, 'B': 0.66}
]

但我找不到从results_index 生成所需多索引的简单方法。

我试过了:

df = pd.DataFrame(results_data, index=results_index)

但它会产生这个:

                     A     B
{'p': 2, 'q': 7}  0.18  0.18
{'p': 2, 'q': 5}  0.67  0.21
{'p': 1, 'q': 4}  0.96  0.45
{'p': 2, 'q': 4}  0.58  0.66

(索引没有转换成MultiIndex)

我想要的是这个:

        A     B
p q            
2 7  0.18  0.18
  5  0.67  0.21
1 4  0.96  0.45
2 4  0.58  0.66

这可行,但必须有更简单的方法:

df = pd.concat([pd.DataFrame(results_index), pd.DataFrame(results_data)], axis=1).set_index(['p', 'q'])

更新:

此外,这可行,但让我感到紧张,因为我如何确保参数值与级别名称对齐?

index = pd.MultiIndex.from_tuples([tuple(i.values()) for i in results_index], 
                                  names=results_index[0].keys())
df = pd.DataFrame(results_data, index=index)

        A     B
p q            
2 7  0.18  0.18
  5  0.67  0.21
1 4  0.96  0.45
2 4  0.58  0.66

【问题讨论】:

  • pd.DataFrame({**x, **y} for x,y in zip(results_index, results_data)).set_index(['p', 'q']) 有效,但老实说与您的 concat 解决方案没有太大区别。

标签: python pandas dictionary dataframe multi-index


【解决方案1】:

我尝试使用 .join()

df1 = pd.DataFrame(results_index)
df2 = pd.DataFrame(results_data)
result = df1.join(df2, how='outer').set_index(['p','q'])

我得到了相同的结果,并且发现这更容易。希望这对您有所帮助。

【讨论】:

    【解决方案2】:

    创建列表字典并传递给MultiIndex.from_arrays

    #https://stackoverflow.com/a/33046935
    d = {k: [dic[k] for dic in results_index] for k in results_index[0]}
    print(d)
    {'p': [2, 2, 1, 2], 'q': [7, 5, 4, 4]}
    
    mux = pd.MultiIndex.from_arrays(list(d.values()), names=list(d))
    
    df = pd.DataFrame(results_data, index=mux)
    print (df)
            A     B
    p q            
    2 7  0.18  0.18
      5  0.67  0.21
    1 4  0.96  0.45
    2 4  0.58  0.66
    

    【讨论】:

    • 是的,我认为因为似乎没有其他方法,最好的办法是首先收集列表中的所有参数值(检查每次迭代是否参数相同并附加到正确的列表),然后在最后使用pd.MultiIndex.from_arrays。似乎没有一种简单的方法可以从字典列表中创建多索引。谢谢。
    • 使用pd.MultiIndex.from_frame查看@santon 的新答案。
    • @Bill 是的,我明白了。
    • 替代pd.MultiIndex.from_tuples: tuples = [tuple(d.values()) for d in results_index]; index = pd.MultiIndex.from_tuples(tuples, names=list(result_index.keys())); df = pd.DataFrame(results_data, index=index)
    【解决方案3】:

    这是@jezrael 答案的变体。稍微简洁一些,并且具有能够处理参数字典中潜在的不一致的好处。但没那么快。

    index_df = pd.DataFrame(results_index)
    index = pd.MultiIndex.from_arrays(index_df.values.transpose(),
                                      names=index_df.columns)
    pd.DataFrame(results_data, index=index)
    

    输出:

            A     B
    p q            
    2 7  0.18  0.18
      5  0.67  0.21
    1 4  0.96  0.45
    2 4  0.58  0.66
    

    【讨论】:

      【解决方案4】:

      我最近遇到了这个问题,似乎有一种比公认的答案更干净的方法:

      results_index = [
          {'p': 2, 'q': 7},
          {'p': 2, 'q': 5},
          {'p': 1, 'q': 4},
          {'p': 2, 'q': 4}
      ]
      
      results_data = [
          {'A': 0.18, 'B': 0.18},
          {'A': 0.67, 'B': 0.21},
          {'A': 0.96, 'B': 0.45},
          {'A': 0.58, 'B': 0.66}
      ]
      
      index = pd.MultiIndex.from_frame(pd.DataFrame(results_index))
      
      pd.DataFrame(results_data, index=index)
      

      输出:

              A     B
      p q            
      2 7  0.18  0.18
        5  0.67  0.21
      1 4  0.96  0.45
      2 4  0.58  0.66
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-10
        • 2020-03-03
        • 2010-11-26
        相关资源
        最近更新 更多