我有一些代码可以加载很长(100k-1mil)的行集,它在第一列中有一个索引,后跟18个值,每行总共19个浮点数。所有这些都放入一个numpy数组中。
我需要对矩阵进行一些简单处理,以保留索引列并根据值是正数还是负数的条件得出1和0,但是准则会有所不同,因为列是具有不同引用的连续值对值。
下面的代码首先通过2-19列进行偶校验,然后用奇数校验值,然后创建一个临时列表以放入我想要的数组末尾。
我知道使用列表理解和lambda可以更简单地做到这一点,但是我对此并不熟练。因此,我希望有人可以帮助我将这段代码的长度缩短为更紧凑的形式。效率也更高,但是我知道紧凑的方法并不总是能提高效率。但是,无论有没有numpy,它都将帮助我更好地理解列表理解。
供参考的样本值:
0.000 72.250 -158.622 86.575 -151.153 85.807 -149.803 84.285 -143.701 77.723 -160.471 96.587 -144.020 75.827 -157.071 87.629 -148.856 100.814 -140.488
10.000 56.224 -174.351 108.309 -154.148 68.564 -155.721 83.634 -132.836 75.030 -177.971 100.623 -146.616 61.856 -150.885 92.147 -150.124 91.841 -153.112
20.000 53.357 -153.537 58.190 -160.235 77.575 176.257 93.771 -150.549 77.789 -161.534 103.589 -146.363 73.623 -159.441 99.315 -129.663 92.842 -138.736
这是代码段:
datain = numpy.loadtxt(testfile.txt) #load data
dataout = numpy.zeros(datain.shape) # initialize empty processing array
dataout[:, 0] = datain[:, 0] # assign time values from input data to processing array
dataarray = numpy.zeros(len(datain[0]))
phit = numpy.zeros((len(dataarray)-1)/2)
psit = numpy.zeros((len(dataarray)-1)/2)
for i in range(len(datain)):
dataarray = numpy.copy(datain[i])
phit[:] = dataarray[1::2]
psit[:] = dataarray[2::2]
temp = []
for j in range(len(phit)):
if(phit[j] < 0):
temp.append(1)
else:
temp.append(0)
if(psit[j] > 0):
temp.append(1)
else:
temp.append(0)
dataout[i][1:] = temp
预先感谢,我知道这里有很多关于这些主题的问题;不幸的是,我找不到能帮助我解决问题的方法。
答案 0 :(得分:2)
正如@abarnert所提到的,这里的解决方案不是编写更好的循环,而是(因为您使用的是Numpy)通过理解如何以更高级的方式使用Numpy来完全不在Python中循环。
您拥有的是像这样的矩阵
[ [idx, v0a, v0b, v1a, v1b, ... ], ... ]
您想要一个基本的矩阵
[ [idx, 1 if v0a < 0 else 0, 1 if v0b > 0 else 0, ... ], ... ]
我们将分两步进行此操作:首先,我们将对矩阵进行稍微变换,以使比较都相同;其次,我们将就地应用比较。
我们如何处理“偶数”和“奇数”列之间的唯一区别是,要检查一个<0,另一个要检查> 0。如果我们通过将它们乘以-1来修改第二组列,则这些比较都将简单地变为<0:
datain[:, 2::2] *= -1
现在,我们只想知道,对于每个值(除第一列之外),该值都是<0。这非常简单:
datain[:, 1:] < 0
这将返回一个布尔值矩阵,其中每个值表示datain[:, 1:]
中的对应单元格是否小于0。您希望将它们作为整数,1表示True,0表示False;事实证明,当我们将这些布尔值分配回我们的原始数组(包含浮点数)时,numpy会自动将布尔值转换为浮点数; True将被强制转换为1.0,而False将被强制转换为0.0。
如果您不想丢弃原始数据,只需先将其复制掉即可。这是完整的代码:
# If you want to preserve your old data, create a copy for us to modify
dataout = np.array(datain)
# Now assign your integer values into your data array
dataout[:, 2::2] *= -1
dataout[:, 1:] = datain[:, 1:] < 0
对于您提供的示例输入:
array([[ 0. , 72.25 , 158.622, 86.575, 151.153, 85.807,
149.803, 84.285, 143.701, 77.723, 160.471, 96.587,
144.02 , 75.827, 157.071, 87.629, 148.856, 100.814,
140.488],
[ 10. , 56.224, 174.351, 108.309, 154.148, 68.564,
155.721, 83.634, 132.836, 75.03 , 177.971, 100.623,
146.616, 61.856, 150.885, 92.147, 150.124, 91.841,
153.112],
[ 20. , 53.357, 153.537, 58.19 , 160.235, 77.575,
-176.257, 93.771, 150.549, 77.789, 161.534, 103.589,
146.363, 73.623, 159.441, 99.315, 129.663, 92.842,
138.736]])
此代码最终具有以下最终结果:
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.],
[10., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.],
[20., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.]])
答案 1 :(得分:1)
感谢abarnert以此向我指出正确的方向,解决方案非常简单。
datain = numpy.loadtxt(testfile.txt) #load data
dataout = numpy.empty(datain.shape, dtype=int) # initialize empty processing array
dataout[:, 0] = datain[:, 0] # assign time values from input data to processing array
dataout[:, 1::2] = datain[:, 1::2] < 0
dataout[:, 2::2] = datain[:, 2::2] > 0
就是这样!更短,更易读,并且为我提供了我想要的值。