【问题标题】:Numpy ValueError: setting an array element with a sequenceNumpy ValueError:使用序列设置数组元素
【发布时间】:2023-06-06 13:17:01
【问题描述】:

当我试图将 mysql 数据转换为一个 numpy 数组(最终是一个列表)时,我得到了Numpy ValueError: setting an array element with a sequence。最初我想拥有多个字段,但我已将代码简化为仅制作一个包含一个字段(整数)的列表以进行故障排除。

我是 numpy 的新手,所以我不确定i4 代表什么(尽管文档说它意味着一个整数......好吧)。至于count,那似乎是指字段数。但是,fromiter 行上的某些内容仍然导致它遇到异常。

import MySQLdb
import numpy

conn = MySQLdb.connect(host="localhost", user="x", passwd="x", db="x")
curs = conn.cursor() 
numrows = curs.execute("select id from table")

A = numpy.fromiter(curs.fetchall(), count=numrows, dtype=('i4'))

print A 
ids = A['f0'] 

追溯:

A = numpy.fromiter(curs.fetchall(), count=1, dtype=('i4'))
ValueError: setting an array element with a sequence.

【问题讨论】:

  • 请将完整的错误回溯添加到您的问题中。
  • 我添加了相关行。除了我已经引用的错误之外,它确实没有显示任何其他内容。
  • 它确实显示了行号以及其他有用的信息。只需将完整的输出复制到您的问题中即可。
  • 整个脚本只有8行。 fromiter 是唯一引发的异常。

标签: python numpy


【解决方案1】:

更正 - 要使用来自 fetchall 的元组列表,dtype 应该生成结构化数组

查看文档,我看到fetch_all 返回的是元组列表,而不是生成器。但这不是这里的问题。两者都是可迭代的。问题出在dtype上。要从元组列表中创建一维数组,fromiter 需要结构化的复合 dtype。

此 dtype 适用于 1 元素元组:

In [355]: np.fromiter([(1,)],dtype=[('f0','i4')])
Out[355]: 
array([(1,)], dtype=[('f0', '<i4')])

这适用于 2 个字段(列)

In [356]: np.fromiter([(1,1)],dtype=('i4,i4'))
Out[356]: 
array([(1, 1)],   dtype=[('f0', '<i4'), ('f1', '<i4')])

但它们是相同的 - 一个普通的非结构化数组。

np.fromiter([(1,)],dtype=('i4'))
np.fromiter([(1,)],dtype=int)

[(1,)] 的处理方式与 [[1]] 相同,它是二维数组的输入,而不是 fromiter 期望的一维迭代。


np.arrayfromiter 在结构化案例中的作用相同:

 np.array([(1,)],dtype=[('f0','i4')])
 np.array([(1,1)],dtype=('i4,i4'))

它也适用于int(或i4),但结果是一个二维数组:

In [366]: np.array([(1,)],dtype=('i4'))
Out[366]: array([[1]])

(早期版本)

我可以通过给fromiter 提供[(1,)] 可迭代来重现您的错误消息。

In [288]: np.fromiter([(1,)],dtype=int)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-288-ba24373a9489> in <module>()
----> 1 np.fromiter([(1,)],dtype=int)

ValueError: setting an array element with a sequence.

fromiter 想要一维输入,例如[1,2,3](或生成器等效项)。

自从我使用 sql 以来已经有一段时间了,但我猜curs.fetchall() 给出了一个元组的可迭代,而不是单个数字的可迭代。

您需要显示(打印)curs.fetchall()list(curs.fetchall()) 以查看传递给 fromiter 的内容。

你为什么使用fromiter?你试过np.array(curs.fetchall())吗?

让我们尝试使用生成器表达式来更好地模拟生成元组的fetchall

In [298]: np.fromiter((i for i in [(1,2,3)]),dtype=int)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-298-f8fbf106b4d1> in <module>()
----> 1 np.fromiter((i for i in [(1,2,3)]),dtype=int)

ValueError: setting an array element with a sequence.
In [299]: np.array((i for i in [(1,2,3)]),dtype=int)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-299-71dd7463b539> in <module>()
----> 1 np.array((i for i in [(1,2,3)]),dtype=int)

TypeError: int() argument must be a string or a number, not 'generator'

这行得通:

In [300]: np.array(list(i for i in [(1,2,3)]),dtype=int)
Out[300]: array([[1, 2, 3]])

In [301]: list(i for i in [(1,2,3)])
Out[301]: [(1, 2, 3)]

创建 numpy 数组的最简单方法是使用列表 - 它可以是数字列表、列表列表(大小相同)或元组列表。

What's the most efficient way to convert a MySQL result set to a NumPy array? 是之前讨论过使用fetchallfromiter


【讨论】:

  • Fromiter 是我在谷歌上找到的。我想要做的就是将 mysql 数据移动到一些列表中,以便我可以绘制数据。
  • 无论如何,让我们清楚您从cur 得到什么。尝试创建一个基本的 Python 列表并显示它。然后我们就可以发np.array了。
  • 谢谢。我仍在研究它,但似乎这与我只使用一个字段(作为测试)的事实有关,但实际上它至少期望 2 个或其他东西。我创建了一个新表,每个表有 2 个整数字段,以进行测试,然后能够毫无例外地运行此代码。
  • 我知道为什么 2 个字段有效,但 1 个无效 - dtype=('i4') 不会产生结构化数组,而 dtype=('i4,i4') 会。