14

我正在尝试将列名添加到 numpy ndarray,然后按名称选择列。但它不起作用。我不知道是在添加名称时出现问题,还是在稍后尝试调用它们时出现问题。

这是我的代码。

data = np.genfromtxt(csv_file, delimiter=',', dtype=np.float, skip_header=1)

#Add headers
csv_names = [ s.strip('"') for s in file(csv_file,'r').readline().strip().split(',')]
data = data.astype(np.dtype( [(n, 'float64') for n in csv_names] ))

基于维度的诊断符合我的预期:

print len(csv_names)
>> 108
print data.shape
>> (1652, 108)

“print data.dtype.names”也返回预期的输出。

但是,当我开始按字段名称调用列时,就会发生一些奇怪的事情。“列”仍然是一个包含 108 列的数组...

print data["EDUC"].shape
>> (1652, 108)

...并且它似乎包含比数据集中的行更多的缺失值。

print np.sum(np.isnan(data["EDUC"]))
>> 27976

知道这里出了什么问题吗?添加标题应该是一个微不足道的操作,但我已经与这个错误作斗争了几个小时。帮助!

4

2 回答 2

15

问题是您正在考虑类似电子表格的数组,而 NumPy 确实使用不同的概念。

以下是您必须了解的有关 NumPy 的信息:

  1. NumPy 数组只包含单一类型的元素。
  2. 如果您需要类似电子表格的“列”,则此类型必须是类似元组的类型。这样的数组称为结构化数组,因为它们的元素是结构(即元组)。

在您的情况下,NumPy 将因此获取您的二维常规数组并生成一个维数组,其类型是 108 个元素的元组(您正在考虑的电子表格数组是二维的)。

这些选择可能是出于效率原因:数组的所有元素都具有相同的类型,因此具有相同的大小:它们可以在低级别非常简单和快速地访问。

现在,正如 user545424 所示,对于您想要做的事情有一个简单的 NumPy 答案(genfromtxt()接受names带有列名的参数)。

如果要将数组从常规 NumPy ndarray 转换为结构化数组,可以执行以下操作:

data.view(dtype=[(n, 'float64') for n in csv_names]).reshape(len(data))

(你很接近:你用astype()而不是view())。

您还可以查看很多 Stackoverflow 问题的答案,包括将 2D numpy 数组转换为结构化数组以及如何将常规 numpy 数组转换为记录数组?.

于 2012-05-25T08:07:36.770 回答
3

不幸的是,当您尝试添加字段名称时,我不知道发生了什么,但我知道您可以通过以下方式直接从文件中构建您想要的数组

data = np.genfromtxt(csv_file, delimiter=',', names=True)

编辑:

似乎添加字段名称仅在输入是元组列表时才有效:

data = np.array(map(tuple,data), [(n, 'float64') for n in csv_names])
于 2012-05-24T18:15:07.280 回答