将字典列表转换为 pandas DataFrame

2024-11-26 08:36:00
admin
原创
191
摘要:问题描述:如何将字典列表转换为 DataFrame?我想将[{'points': 50, 'time': '5:00', 'year': 2010}, {'points': 25, 'time': '6:00', 'month': "february"}, {'points':90...

问题描述:

如何将字典列表转换为 DataFrame?我想将

[{'points': 50, 'time': '5:00', 'year': 2010}, 
 {'points': 25, 'time': '6:00', 'month': "february"}, 
 {'points':90, 'time': '9:00', 'month': 'january'}, 
 {'points_h1':20, 'month': 'june'}]

进入

      month  points  points_h1  time  year
0       NaN      50        NaN  5:00  2010
1  february      25        NaN  6:00   NaN
2   january      90        NaN  9:00   NaN
3      june     NaN         20   NaN   NaN

解决方案 1:

如果ds是 s 的列表dict

df = pd.DataFrame(ds)

注意:这不适用于嵌套数据。

解决方案 2:

如何将字典列表转换为 pandas DataFrame?

其他答案都是正确的,但关于这些方法的优点和局限性的解释并不多。这篇文章的目的是展示这些方法在不同情况下的示例,讨论何时使用(何时不使用),并提出替代方案。


DataFrame()DataFrame.from_records(), 和.from_dict()

根据数据的结构和格式,在某些情况下,三种方法都有效,或者某些方法比其他方法效果更好,或者某些方法根本不起作用。

考虑一个非常不自然的例子。

np.random.seed(0)
data = pd.DataFrame(
    np.random.choice(10, (3, 4)), columns=list('ABCD')).to_dict('r')

print(data)
[{'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]

此列表由包含所有键的“记录”组成。这是您可能遇到的最简单的情况。

# The following methods all produce the same output.
pd.DataFrame(data)
pd.DataFrame.from_dict(data)
pd.DataFrame.from_records(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

字典中的单词方向:orient='index'/'columns'

在继续之前,重要的是要区分不同类型的字典方向以及 pandas 的支持。主要有两种类型:“列”和“索引”。

orient='columns'

具有“列”方向的字典的键将与等效 DataFrame 中的列相对应。

例如,data上面是以“列”为方向的。

data_c = [
 {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]
pd.DataFrame.from_dict(data_c, orient='columns')

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

注意:如果您正在使用pd.DataFrame.from_records,则方向被假定为“列”(您不能另行指定),并且字典将相应地加载。

orient='index'

按照这种思路,键被假定与索引值相对应。这种数据最适合pd.DataFrame.from_dict

data_i ={
 0: {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 1: {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 2: {'A': 2, 'B': 4, 'C': 7, 'D': 6}}
pd.DataFrame.from_dict(data_i, orient='index')

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

OP 中没有考虑这种情况,但了解一下仍然有用。

设置自定义索引

如果您需要在结果 DataFrame 上自定义索引,则可以使用index=...参数进行设置。

pd.DataFrame(data, index=['a', 'b', 'c'])
# pd.DataFrame.from_records(data, index=['a', 'b', 'c'])

   A  B  C  D
a  5  0  3  3
b  7  9  3  5
c  2  4  7  6

这不受支持pd.DataFrame.from_dict

处理缺失的键/列

处理缺少键/列值的字典时,所有方法均可立即使用。例如,

data2 = [
     {'A': 5, 'C': 3, 'D': 3},
     {'A': 7, 'B': 9, 'F': 5},
     {'B': 4, 'C': 7, 'E': 6}]
# The methods below all produce the same output.
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)

     A    B    C    D    E    F
0  5.0  NaN  3.0  3.0  NaN  NaN
1  7.0  9.0  NaN  NaN  NaN  5.0
2  NaN  4.0  7.0  NaN  6.0  NaN

正在读取列的子集

“如果我不想读取每一列怎么办?”您可以使用columns=...参数轻松指定这一点。

例如,从data2上面的示例字典中,如果您只想读取“A”、“D”和“F”列,则可以通过传递列表来实现:

pd.DataFrame(data2, columns=['A', 'D', 'F'])
# pd.DataFrame.from_records(data2, columns=['A', 'D', 'F'])

     A    D    F
0  5.0  3.0  NaN
1  7.0  NaN  5.0
2  NaN  NaN  NaN

pd.DataFrame.from_dict默认的东方“列”不支持这一点。

pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'

读取行子集

这些方法均不直接支持。您必须迭代数据并在迭代时就地执行反向删除。例如,若要仅提取上面的第0 行和第 2行,data2您可以使用:

rows_to_select = {0, 2}
for i in reversed(range(len(data2))):
    if i not in rows_to_select:
        del data2[i]

pd.DataFrame(data2)
# pd.DataFrame.from_dict(data2)
# pd.DataFrame.from_records(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

灵丹妙药:json_normalize针对嵌套数据

上述方法的一个强大而稳健的替代方法是json_normalize使用字典(记录)列表的函数,此外还可以处理嵌套字典。

pd.json_normalize(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6
pd.json_normalize(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

再次提醒,请记住传递的数据json_normalize需要采用字典列表(记录)格式。

如上所述,json_normalize还可以处理嵌套字典。以下是取自文档的一个例子。

data_nested = [
  {'counties': [{'name': 'Dade', 'population': 12345},
                {'name': 'Broward', 'population': 40000},
                {'name': 'Palm Beach', 'population': 60000}],
   'info': {'governor': 'Rick Scott'},
   'shortname': 'FL',
   'state': 'Florida'},
  {'counties': [{'name': 'Summit', 'population': 1234},
                {'name': 'Cuyahoga', 'population': 1337}],
   'info': {'governor': 'John Kasich'},
   'shortname': 'OH',
   'state': 'Ohio'}
]
pd.json_normalize(data_nested, 
                          record_path='counties', 
                          meta=['state', 'shortname', ['info', 'governor']])

         name  population    state shortname info.governor
0        Dade       12345  Florida        FL    Rick Scott
1     Broward       40000  Florida        FL    Rick Scott
2  Palm Beach       60000  Florida        FL    Rick Scott
3      Summit        1234     Ohio        OH   John Kasich
4    Cuyahoga        1337     Ohio        OH   John Kasich

有关metarecord_path参数的更多信息,请查看文档。


总结

以下是上面讨论的所有方法以及支持的特性/功能的表格。

在此处输入图片描述

  • 使用orient='columns'然后转置 可获得与 相同的效果orient='index'

解决方案 3:

在 pandas 16.2 中,我必须pd.DataFrame.from_records(d)这样做才能使其正常工作。

解决方案 4:

您还可以使用pd.DataFrame.from_dict(d)

In [8]: d = [{'points': 50, 'time': '5:00', 'year': 2010}, 
   ...: {'points': 25, 'time': '6:00', 'month': "february"}, 
   ...: {'points':90, 'time': '9:00', 'month': 'january'}, 
   ...: {'points_h1':20, 'month': 'june'}]

In [12]: pd.DataFrame.from_dict(d)
Out[12]: 
      month  points  points_h1  time    year
0       NaN    50.0        NaN  5:00  2010.0
1  february    25.0        NaN  6:00     NaN
2   january    90.0        NaN  9:00     NaN
3      june     NaN       20.0   NaN     NaN

解决方案 5:

Pyhton3:
前面列出的大多数解决方案都有效。但是,有些情况下不需要数据框的 row_number,并且必须单独写入每一行(记录)。

在这种情况下,下面的方法很有用。

import csv

my file= 'C:UsersJohnDesktopexport_dataframe.csv'

records_to_save = data2 #used as in the thread. 


colnames = list[records_to_save[0].keys()] 
# remember colnames is a list of all keys. All values are written corresponding
# to the keys and "None" is specified in case of missing value 

with open(myfile, 'w', newline="",encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(colnames)
    for d in records_to_save:
        writer.writerow([d.get(r, "None") for r in colnames])

解决方案 6:

如果字典中缺少键,简单的pd.DataFrame()构造将通过为缺少的键分配 NaN 值来处理它。这会“弄乱”数据类型并将整数转换为浮点数。例如,使用 OP 中的示例数据,'year'列中缺少值,这些值会转换为浮点数,这可能不是我们所希望的,因为我们现在有可空的整数数据类型。解决这个问题的一种方法是无论如何都要构造数据框,然后稍后使用来处理数据类型astype()

lst = [{'points': 50, 'time': '5:00', 'year': 2010}, 
       {'points': 25, 'time': '6:00', 'month': "february"}, 
       {'points':90, 'time': '9:00', 'month': 'january'}, 
       {'points_h1':20, 'month': 'june'}]

dtypes = {'points': 'Int32', 'time': 'string', 'year': 'Int32', 'month': 'string', 'points_h1': 'Int32'}
df = pd.DataFrame(lst).astype(dtypes)

但是,如果键很多,则扩展性不佳。一种简单的开箱即用方法是将列表转换为 json 数组,然后使用 将其读取为 json pd.read_json。它的好处是,您可以在构造期间设置 dtype,将整数转换为 Int dtype,但保留其他所有内容(例如字符串、浮点数等)不变。

import json, io  # both of these are in the standard library
df = pd.read_json(io.StringIO(json.dumps(lst)), dtype='Int32')

结果

解决方案 7:

我发现最简单的方法是这样的:

dict_count = len(dict_list)
df = pd.DataFrame(dict_list[0], index=[0])
for i in range(1,dict_count-1):
    df = df.append(dict_list[i], ignore_index=True)

解决方案 8:

我有以下带有datetime键和 int 值的字典列表:

list = [{datetime.date(2022, 2, 10): 7}, 
        {datetime.date(2022, 2, 11): 1}, 
        {datetime.date(2022, 2, 11): 1}]

Dataframe我在使用上述方法将其转换为时遇到了问题,因为它创建了一个Dataframe带有日期的列......

我的解决方案:

df = pd.DataFrame()
for i in list:
    temp_df = pd.DataFrame.from_dict(i, orient='index')
    df = df.append(temp_df)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用