以编程方式将列名添加到numpy ndarray

时间:2012-05-24 17:26:50

标签: python arrays numpy multidimensional-array

我正在尝试将列名添加到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

知道这里出了什么问题吗?添加标题应该是一个简单的操作,但我已经打了几个小时这个bug。救命啊!

2 个答案:

答案 0 :(得分:15)

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

以下是你必须了解的NumPy:

  1. NumPy数组仅包含单一类型的元素。
  2. 如果您需要类似电子表格的"列",此类型必须是一些类似元组的类型。这种数组称为结构化数组,因为它们的元素是结构(即元组)。
  3. 在你的情况下,NumPy会因此获取你的二维常规数组并生成一个一个维数组,其类型是一个108元素的元组(你想到的电子表格数组是2维)。

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

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

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

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

    (你很接近:你使用astype()代替view())。

    您还可以查看相当多的Stackoverflow问题的答案,包括Converting a 2D numpy array to a structured arrayhow to convert regular numpy array to record array?

答案 1 :(得分:3)

不幸的是,当你尝试添加字段名称时我不知道发生了什么,但我知道你可以通过

直接从文件构建你想要的数组。
data = np.genfromtxt(csv_file, delimiter=',', names=True)

编辑:

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

data = np.array(map(tuple,data), [(n, 'float64') for n in csv_names])