将列表的字典展平为数据框

Posted

技术标签:

【中文标题】将列表的字典展平为数据框【英文标题】:Flatten of dict of lists into a dataframe 【发布时间】:2019-01-10 05:57:49 【问题描述】:

我有一个列表说: data = 'a': [80, 130], 'b': [64], 'c': [58,80] 如何将其展平并将其转换为如下所示的数据框:

【问题讨论】:

【参考方案1】:

扁平化字典的一个选项是

flattened_data = 
    k + str(i): x
    for k, v in data.items()
    for i, x in enumerate(v)

导致

'a0': 80, 'a1': 130, 'b0': 64, 'c0': 58, 'c1': 80

如果您坚持从 1 开始索引,则可以使用 enumerate(v, 1) 而不是 enumerate(v)。如果您想在列表只有一个条目的情况下省略索引,则应使用 for 循环而不是字典推导式。

【讨论】:

感谢您的回答..如果值是非整数说浮点数,我得到一个 TypeError :'float' object is not iterable..如果我该怎么办值是浮动的? @Sven Marnach 这也是我首先想到的。使用 enumerate 上的 start 参数的 f 字符串变体:f"ki": v for k, vs in data.items() for i, v in enumerate(vs, 1) 或者,当只有一个值存在时捕获'b' f"k'' if len(vs) == 1 else i" for k, vs in data.items() for i, v in enumerate(vs, 1)【参考方案2】:

如果不希望有一个元素列表,请使用带有 if-else 的嵌套列表推导:

df = pd.DataFrame([(''.format(k, i), v1) 
                   if len(v) > 1
                   else (k, v1) 
                   for k, v in data.items() 
                   for i, v1 in enumerate(v, 1)], columns=['Index','Data'])
print (df)
  Index  Data
0    a1    80
1    a2   130
2     b    64
3    c1    58
4    c2    80

编辑:

data = 'a': [80, 130], 'b': np.nan, 'c': [58,80], 'd':[34]

out = []
for k, v in data.items():
    if isinstance(v, float):
        out.append([k, v])
    else:
        for i, x in enumerate(v, 1):
            if len(v) == 1:
                out.append([k, x])
            else:
                out.append([''.format(k, i), x])
print (out)
[['a1', 80], ['a2', 130], ['b', nan], ['c1', 58], ['c2', 80], ['d', 34]]


df = pd.DataFrame(out, columns=['Index','Data'])
print (df)
  Index   Data
0    a1   80.0
1    a2  130.0
2     b    NaN
3    c1   58.0
4    c2   80.0
5     d   34.0

【讨论】:

感谢您的回答..如果值是非整数说浮点数,我得到一个 TypeError :'float' object is not iterable..如果我该怎么办值是浮动的? @RemyM - 不容易,因为似乎有些浮动与列表混合在一起。【参考方案3】:

使用pd.DataFrame 构造函数和GroupBy + cumcount

data = 'a': [80, 130], 'b': [64], 'c': [58,80]

df = pd.DataFrame([[k, w] for k, v in data.items() for w in v],
                  columns=['Index', '0'])

df['Index'] = df['Index'] + (df.groupby('Index').cumcount() + 1).astype(str)

print(df)

  Index    0
0    a1   80
1    a2  130
2    b1   64
3    c1   58
4    c2   80

【讨论】:

【参考方案4】:

另一种方法是使用from_dict,将orient参数设置为'index'和stack,最后使用mapformat将索引中的多级展平:

df = pd.DataFrame.from_dict(data, orient='index')
df_out = df.rename(columns=lambda x: x+1).stack()
df_out.index = df_out.index.map('0[0]0[1]'.format)
print(df_out)

输出:

a1     80.0
a2    130.0
b1     64.0
c1     58.0
c2     80.0
dtype: float64

【讨论】:

【参考方案5】:

使用itertoolspd.io._maybe_dedup_names

x = (itertools.product(s[0],s[1]) for s in data.items())
z = [item for z in x for item in z]
df = pd.DataFrame(z).set_index(0)
df.index = pd.io.parsers.ParserBase('names':df.index)._maybe_dedup_names(df.index)

    1
a   80
a.1 130
b   64
c   58
c.1 80

【讨论】:

【参考方案6】:

Sven Marnach's 答案的变化让我很开心

defaultdictcount

from collections import defaultdict
from itertools import count

c = defaultdict(lambda:count(1))

f"k['', next(c[k])][len(V) > 1]": v for k, V in data.items() for v in V

'a1': 80, 'a2': 130, 'b': 64, 'c1': 58, 'c2': 80

enumerate

f"k['', i][len(V) > 1]": v for k, V in data.items() for i, v in enumerate(V, 1)

'a1': 80, 'a2': 130, 'b': 64, 'c1': 58, 'c2': 80

【讨论】:

【参考方案7】:

Imo 你应该首先得到 dict 根列表和 dict 叶列表。

像这样:[a,b,c][[80,130],[64],[58,80]]

然后只需将它们与循环并行化即可获得

[a1,a2,b,c1,c2][80,130,64,58,80](这应该只需要几行代码)

然后将其加载到数据框中。

如果你需要更精确的代码,你可以问:)

【讨论】:

以上是关于将列表的字典展平为数据框的主要内容,如果未能解决你的问题,请参考以下文章

如何使用嵌套字典列表展平熊猫数据框中的列

如何展平熊猫数据框多列中的字典列表

以独特的方式展平包含嵌套字典的列表的数据框列

将嵌套命名元组的列表展平为字典列表

如何展平此数据框

将任意长度的字典项展平为 Python 中的路径列表