如何在 Python 中忽略 nan 的列堆栈数组?

How to column stack arrays ignoring nan in Python?

我在文本文件中有表格的数据。

文本文件条目

#x  y   z
1   1   1
2   4   
3   9   
4   16  
5   25  
6   36  
7   49  
8   64  512
9   81  729
10  100 1000
11  121 
12  144 1728
13  169 
14  196 
15  225 
16  256 4096
17  289 
18  324 
19  361 6859
20  400 
21  441 9261
22  484 
23  529 12167
24  576 
25  625

第三列中的一些条目是空的。我正在尝试创建一个忽略 nan 的 x(第 1 列)和 z(第 3 列)数组。设数组为B,B的内容应为:

1   1
8   512
9   729
10  1000
12  1728
16  4096
19  6859
21  9261
23  12167

我尝试使用以下代码执行此操作:

import numpy as np
A = np.genfromtxt('data.dat', comments='#', delimiter='\t')
B = []
for i in range(len(A)):
    if ~ np.isnan(A[i, 2]):
        B =  np.append(B, np.column_stack((A[i, 0], A[i, 2])))
print B.shape

这不起作用。它创建一个列向量。如何在 Python 中完成?

如果您阅读 data.dat 文件并将内容分配给变量,请说 data:

您可以遍历这些行并将它们拆分并仅处理具有 3 个元素的行:

B=[]
for line in data.split('\n'):
    if len(line.split()) == 3:
        x,y,z = line.split()
        B.append((x,z)) # or B.append(str(x)+'\t'+str(z)+'\n')
                        # or any othr format you need

正如您发现的那样,库提供的功能并不总是易于使用。以下程序手动执行此操作,并使用数据文件中的值创建一个数组。

import numpy as np

def main():
    B = np.empty([0, 2], dtype = int)
    with open("data.dat") as inf:
        for line in inf:
            if line[0] == "#": continue
            l = line.split()
            if len(l) == 3:
                l = [int(d) for d in l[1:]]
                B = np.vstack((B, l))

    print B.shape
    print B

    return 0

if __name__ == '__main__':
    main()

注意:

1) append() 函数适用于列表,不适用于数组 - 至少不适用于您使用的语法。扩展数组的最简单方法是 'piling' 行,使用 vstack(或 hstack 列)

2) 在 genfromtxt() 中指定分隔符可能会害了你。默认情况下,分隔符是任何白色 space,这通常是您想要的。

使用pandas会让你的生活更轻松(注意定义delimiter的正则表达式):

from pandas import read_csv

data = read_csv('data.dat', delimiter='\s+').values

print(data[~np.isnan(data[:, 2])][:, [0, 2]])

这导致:

array([[  8.00000000e+00,   5.12000000e+02],
       [  9.00000000e+00,   7.29000000e+02],
       [  1.00000000e+01,   1.00000000e+03],
       [  1.20000000e+01,   1.72800000e+03],
       [  1.60000000e+01,   4.09600000e+03],
       [  1.90000000e+01,   6.85900000e+03],
       [  2.10000000e+01,   9.26100000e+03],
       [  2.30000000e+01,   1.21670000e+04]])

来自您的输入数据框:

In [33]: df.head()
Out[33]: 
   x   y   z
0  1   1   1
1  2   4 NaN
2  3   9 NaN
3  4  16 NaN
4  5  25 NaN

..你可以通过这样做得到输出数据帧B:

In [34]: df.dropna().head().drop('y', axis=1)
Out[34]: 
     x     z
0    1     1
7    8   512
8    9   729
9   10  1000
11  12  1728