【问题标题】:Convert psycopg2 DictRow query to Pandas dataframe将 psycopg2 DictRow 查询转换为 Pandas 数据帧
【发布时间】:2016-02-24 13:58:31
【问题描述】:

我想将 psycopg2 DictRow 查询转换为 pandas 数据框,但 pandas 一直在抱怨:

curs = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
curs.execute("SELECT * FROM mytable")
data = curs.fetchall()

print type(data)
print pd.DataFrame(list(data))

但是,尽管我专门传递了list???,但我总是收到错误消息?

<type 'list'>
TypeError: Expected list, got DictRow

如果我做pd.DataFrame(data),结果是一样的,有人可以帮我完成这项工作吗?

如果数据框的列名有效(即提取 DictRow 并将它们传递给数据框)也会很好。

更新:
由于我需要处理数据,我想按原样使用来自 psycopg2 查询的数据,而不是 pandas approach,例如read_sql_query

【问题讨论】:

标签: python pandas psycopg2


【解决方案1】:

更新:pandas.read_sql_query() 是一种将 SQL 查询读入数据帧的更优雅的方式,无需psycopg2。请参阅pandas docs

我也遇到了同样的问题。我发现最简单的方法是将 DictRow 转换为 numpy 数组。

import numpy as np
curs = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
curs.execute("SELECT * FROM mytable")
data = curs.fetchall()

print type(data)
print pd.DataFrame(np.array(data))

如果要获取列名,可以将它们作为DictRow 的每一行的键来访问。但是,转换为 numpy 数组不会保留顺序。所以一种(不优雅的)方式如下:

curs = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
curs.execute("SELECT * FROM mytable")
data = curs.fetchall()

print type(data)
colNames = data[0].keys()
print pd.DataFrame([[row[col] for col in colNames] for row in data], columns=colNames)

【讨论】:

  • pandas.read_sql_query 确实更优雅,但您的解决方案对于那些可能不想创建对 sqlalchemy 的依赖的人来说更可取。
【解决方案2】:

嗯,我最终找到了这个 hacky 解决方案:

print pd.DataFrame([i.copy() for i in data])

DictRow 类的copy() 函数将返回一个实际的字典。通过列表理解,我创建了一个(相同的)字典列表,Pandas 会很乐意接受。

我仍然不明白为什么list(data) 产生了TypeError。也许有人仍然可以启发我。

【讨论】:

  • 因为行是psycopg2.DictType 你可以在下面看到我的答案
【解决方案3】:

您确实需要先解析出元素。您可能会感到困惑,因为整个结果是 DictRow 元素的列表,但 element 不是列表。因此在pandas 0.22.0 中,即使阅读from_records 也不会立即起作用。

这适用于原生类型:

inp = [{'a': 1}, {'b': 2}, {'a': 1}, {'b': 2}, {'a': 1}, {'b': 2}]
>>> pd.DataFrame(inp)
     a    b
0  1.0  NaN
1  NaN  2.0
2  1.0  NaN
3  NaN  2.0
4  1.0  NaN
5  NaN  2.0

但是打印 Psycopg2 查询的结果可能是混淆的根源(自己的数据):

[[157, 158, 83, 1], [157, 159, 47, 1], [158, 157, 53, 1], [158, 159, 38, 1], [159, 157, 76, 1], [159, 158, 24, 1]] &lt;class 'list'&gt;但其实是第一个元素[157, 158, 83, 1] &lt;class 'psycopg2.extras.DictRow'&gt;

【讨论】:

    猜你喜欢
    • 2021-12-20
    • 2017-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2016-09-27
    相关资源
    最近更新 更多