将列表的字典展平到数据框中

时间:2018-08-02 12:44:49

标签: python pandas dictionary flatten

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

enter image description here

7 个答案:

答案 0 :(得分:4)

一种扁平化字典的方法是

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循环,而不要使用字典理解。

答案 1 :(得分:2)

使用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

答案 2 :(得分: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

答案 3 :(得分:2)

另一种方法是使用foreach {option value} $args { ,并将from_dict参数设置为'index'和orient,最后使用stackmap展平索引中的多级:

format

输出:

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)

答案 4 :(得分:1)

使用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

答案 5 :(得分:1)

我很喜欢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}

答案 6 :(得分:0)

Imo,您首先应该获得字典根目录列表和字典叶子列表。

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

然后将它们与循环并行化以获得

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

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

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