PYODBC 到 Pandas - DataFrame 不起作用 - 传递值的形状是(x,y),索引暗示(w,z)

Posted

技术标签:

【中文标题】PYODBC 到 Pandas - DataFrame 不起作用 - 传递值的形状是(x,y),索引暗示(w,z)【英文标题】:PYODBC to Pandas - DataFrame not working - Shape of passed values is (x,y), indices imply (w,z) 【发布时间】:2013-12-02 01:03:39 【问题描述】:

我之前使用 pyodbc 和 python,但现在我已经将它安装在一台新机器上(win 8 64 位,Python 2.7 64 位,PythonXY 和 Spyder)。

以前我用过(在底部可以找到更多真实的例子):

columns = [column[0] for column in cursor.description]
temp = cursor.fetchall()
data = pandas.DataFrame(temp,columns=columns)

它会正常工作。现在似乎 DataFrame 不再能够从从游标中获取的数据进行转换了。它返回:

传递值的形状是 (x,y),索引表示 (w,z)

我有点明白问题出在哪里。基本上,想象我只取一行。然后 DataFrame 想对其进行整形(1,1),只有一个元素。虽然我想要 (1,X) 其中 X 是列表的长度。

我不确定为什么行为会改变。也许是我拥有的 Pandas 版本,或者 pyodbc,但更新是有问题的。我试图更新一些模块,但它搞砸了一切,我使用的任何方法(二进制文件——用于正确的机器/安装——pip 安装、易于安装、任何东西!等等。这确实非常令人沮丧。我可能会避免从现在开始为 Python Win 8 64 位)。

实例:

sql = 'Select * form TABLE'
cursor.execute(sql)
columns = [column[0] for column in cursor.description]
data    = cursor.fetchall()
        con.close()
            results = DataFrame(data, columns=columns)

返回: * ValueError: 传递值的形状是 (1, 1540),索引暗示 (51, 1540)

注意:

ipdb> type(data)
<type 'list'>
ipdb> np.shape(data)
(1540, 51)
ipdb> type(data[0])
<type 'pyodbc.Row'>

现在,例如,如果我们这样做:

ipdb> DataFrame([1,2,3],columns=['a','b','c'])

* ValueError: 传递值的形状是 (1, 3),索引意味着 (3, 3)

如果我们这样做:

ipdb> DataFrame([[1,2,3]],columns=['a','b','c'])

a b c 0 1 2 3

但是,即使尝试:

ipdb> DataFrame([data[0]], columns=columns)
*** ValueError: Shape of passed values is (1, 1), indices imply (51, 1)

ipdb> DataFrame(data[0], columns=columns)
*** PandasError: DataFrame constructor not properly called!

请帮忙 :) 谢谢!

【问题讨论】:

问题是……? temp 是干什么用的,data 来自哪里? 添加样本数据将提高答案的可能性。 当然,问题是如何摆脱错误并让 DataFrame(data,columns=columns) 工作。我在上面说过:我想要 (1,X) 其中 X 是列表的长度。 为什么需要指定列名? pandas 会自动检测到它们。 pandas.read_sql(query_string, cnxn_obj) 【参考方案1】:

这是因为游标返回的不是元组列表,而是 Row 对象的列表,它们实际上类似于元组,更好,但它们混淆了 pandas 数据帧构造函数。在原始示例中,在创建数据框之前执行此操作:

for i in range(0,len(temp)):
    temp[i]=tuple(temp[i])

【讨论】:

Gena,你真是个天才。我花了几个小时在 SO 上尝试所有其他解决方案,而你的解决方案奏效了。 df = pandas.DataFrame([tuple(t) for t in cursor.fetchall()]) 恕我直言,这应该是公认的答案。 @MortenB 有一个漂亮的解决方案。 temp = map(tuple, temp) 更好【参考方案2】:

从 Pandas 0.12 开始(我相信)你可以这样做:

import pandas
import pyodbc

sql = 'select * from table'
cnn = pyodbc.connect(...)

data = pandas.read_sql(sql, cnn)

在 0.12 之前,您可以这样做:

import pandas
from pandas.io.sql import read_frame
import pyodbc

sql = 'select * from table'
cnn = pyodbc.connect(...)

data = read_frame(sql, cnn)

【讨论】:

它给出了类似的错误!事实上,正如我所提到的,我的代码以前也可以工作。因此,一定是 pyodbc 改变了一些东西?文件“xxx.py”,第 253 行,在 xxx 结果中 = read_frame(sql,con);文件“C:\Python27\lib\site-packages\pandas\io\sql.py”,第 162 行,在 read_frame coerce_float=coerce_float) 文件“C:\Python27\lib\site-packages\pandas\core\frame. py”,第 1115 行,在 from_records 列中) 文件“C:\Python27\lib\site-packages\pandas\core\frame.py”,第 5338 行,在 _arrays_to_mgr 返回 create_block_manager_from_arrays(arrays,arr_names,axes) 文件“C:\Python27 \lib\site-packages\pandas\core\internals.py",第 1825 行,在 create_block_manager_from_arrays construction_error(len(arrays),arrays[0].shape[1:],axes) 文件“C:\Python27\lib\ site-packages\pandas\core\internals.py", line 1799, in construction_error tuple(map(int, [len(ax) for ax in axes])))) ValueError: 传递值的形状是 (51,),指数暗示 (51, 1402) 明确地说,这发生在我的所有机器上,2 台台式机和 1 台笔记本电脑。以前没有发生过(我更新了所有这些:/) @user1350191 我无法使用 pyodbc 3.0.6 重现此问题。当您尝试我的方法时,您能否编辑您的问题以确切地向我展示您在做什么? (显然,省略您的数据库密码等)。 它非常基本,与您所写的相似。只要我有大约 10 分钟的空闲时间,我就会看看我能做什么。同时,考虑到我在 Python 2.7 中使用了 pyodbc 3.0.7(32 位和 64 位都出现了同样的问题,pythonxy 和 anaconda 分布也是如此)。

以上是关于PYODBC 到 Pandas - DataFrame 不起作用 - 传递值的形状是(x,y),索引暗示(w,z)的主要内容,如果未能解决你的问题,请参考以下文章

PYODBC 到 Pandas - DataFrame 不起作用 - 传递值的形状是(x,y),索引暗示(w,z)

PYODBC到Pandas - DataFrame不工作 - 传递值的形状是(x,y),索引暗示(w,z)

并行化 pandas pyodbc SQL 数据库调用

使用 pyODBC 的 fast_executemany 加速 pandas.DataFrame.to_sql

Pandas 与 to_sql 的 ODBC 连接

如果数据类型错误,如何跳过加载到 Pandas 数据框的 excel 文件的行(检查类型)