【问题标题】:Pandas: MultiIndex from Nested DictionaryPandas:嵌套字典中的 MultiIndex
【发布时间】:2022-01-22 10:12:39
【问题描述】:

假设我有一个格式如下的嵌套字典:

dictionary={
     "A":[1, 2],
     "B":[2, 3],
     "Coords":[{
        "X":[1,2,3],
        "Y":[1,2,3],
        "Z":[1,2,3],
     },{
        "X":[2,3],
        "Y":[2,3],
        "Z":[2,3],
     }]
 }

如何将其转换为 Pandas MultiIndex Dataframe?

同样,我怎样才能生成一个数据框,其中行中的信息不针对每个坐标重复?

在我的想象中,两行输出DataFrame应该如下所示:

Index A   B   Coords 
---------------------
0      1   2   X Y Z
              1 1 1
              2 2 2
              3 3 3
--------------------
---------------------
1      2   3   X Y Z
              2 2 2
              3 3 3
--------------------

【问题讨论】:

  • Coords 应该在您的数据框中使用哪种对象?不同数据类型的混合?
  • 坐标是浮点数的二维列表,不多不少。理想情况下,我希望能够以与 Dataframe 相同的方式访问列表,这样 Coords 本身的行为就像或可以轻松地变成 Dataframe 本身。
  • 那么,我想 Coords 是一个 DataFrame。我希望的是 df.iloc[0]["A"] 返回 1 和 df.iloc[0]["X"].iloc[0] 返回 1

标签: python pandas


【解决方案1】:

从你的字典:

>>> import pandas as pd

>>> df = pd.DataFrame.from_dict(dictionary)
>>> df
    A   B   Coords
0   1   2   {'X': [1, 2, 3], 'Y': [1, 2, 3], 'Z': [1, 2, 3]}
1   2   3   {'X': [2, 3], 'Y': [2, 3], 'Z': [2, 3]}

然后我们可以使用pd.Series提取Coords列中dict中的数据,如下所示:

df_concat = pd.concat([df.drop(['Coords'], axis=1), df['Coords'].apply(pd.Series)], axis=1)
>>> df_concat
    A   B   X           Y           Z
0   1   2   [1, 2, 3]   [1, 2, 3]   [1, 2, 3]
1   2   3   [2, 3]      [2, 3]      [2, 3]

最后,我们使用explode 方法将列表作为行获取,并在AB 列上设置索引以获得预期结果:

>>> df_concat.explode(['X', 'Y', 'Z']).reset_index().set_index(['index', 'A', 'B'])
                X   Y   Z
index   A   B           
0       1   2   1   1   1
            2   2   2   2
            2   3   3   3
1       2   3   2   2   2
            3   3   3   3

更新:

如果您使用的是低于 1.3.0 的 Pandas 版本,我们可以使用 @MillerMrosek 在此 answer 中给出的技巧:

def explode(df, columns):
    df['tmp']=df.apply(lambda row: list(zip(*[row[_clm] for _clm in columns])), axis=1) 
    df=df.explode('tmp')
    df[columns]=pd.DataFrame(df['tmp'].tolist(), index=df.index)
    df.drop(columns='tmp', inplace=True)
    return df

explode(df_concat, ["X", "Y", "Z"]).reset_index().set_index(['index', 'A', 'B'])

输出:

                X   Y   Z
index   A   B           
0       1   2   1   1   1
            2   2   2   2
            2   3   3   3
1       2   3   2   2   2
            3   3   3   3

【讨论】:

  • 您好!非常感谢!我已按照您的方法处理我的数据,但出现以下错误:“列必须是标量”。我不太明白为什么会这样。
  • 我明白了,我使用的是最新版本的 Pandas (>=1.3.0),它允许我在多个列上创建 explode。您可以更新更新版本的 Pandas (pip install pandas==1.3.5) 还是更喜欢保留当前版本?
  • 如果您希望继续使用当前的 Pandas 版本,我刚刚更新了解决问题的答案 :)
  • 这太完美了!我做了一些细微的调整,以允许用户在列表中提供他们的列。如果可以,我会编辑?
  • 完美!是的,当然!
猜你喜欢
  • 2015-08-03
  • 2019-07-26
  • 1970-01-01
  • 2018-05-05
  • 2022-01-01
  • 2023-03-30
  • 1970-01-01
  • 2016-07-24
  • 2019-11-15
相关资源
最近更新 更多