【发布时间】:2019-04-11 18:04:24
【问题描述】:
我需要从 numpy 数组(或 pandas 数据框)中创建一个对象列表。每行包含对象的所有属性值(参见示例)。
import numpy as np
class Dog:
def __init__(self, weight, height, width, girth):
self.weight = weight
self.height = height
self.width = width
self.girth = girth
dogs = np.array([[5, 100, 50, 80], [4, 80, 30, 70], [7, 120, 60, 90], [2, 50, 30, 50]])
# list comprehension with idexes
dog_list = [Dog(dogs[i][0], dogs[i][1], dogs[i][2], dogs[i][3]) for i in range(len(dogs))]
我的真实数据当然要大得多(多达一百万行,5 列),因此逐行迭代并查找正确的索引需要很长时间。有没有办法对此进行矢量化或通常使其更高效/更快?我试着自己寻找方法,但我找不到任何可翻译的东西,至少在我的专业水平上是这样。
保留行的顺序非常重要,所以如果这不起作用,我想我将不得不忍受缓慢的操作。
干杯!
编辑 - 关于 np.vectorize 的问题:
这是我实际代码的一部分以及一些实际数据:
将 numpy 导入为 np
class Particle:
TrackID = 0
def __init__(self, uniq_ident, intensity, sigma, chi2, past_nn_ident, past_distance, aligned_x, aligned_y, NeNA):
self.uniq_ident = uniq_ident
self.intensity = intensity
self.sigma = sigma
self.chi2 = chi2
self.past_nn_ident = past_nn_ident
self.past_distance = past_distance
self.aligned_y = aligned_y
self.aligned_x = aligned_x
self.NeNA = NeNA
self.new_track_length = 1
self.quality_pass = True
self.re_seeder(self.NeNA)
def re_seeder(self, NeNA):
if np.isnan(self.past_nn_ident):
self.newseed = True
self.new_track_id = Particle.TrackID
print(self.new_track_id)
Particle.TrackID += 1
else:
self.newseed = False
self.new_track_id = None
data = np.array([[0.00000000e+00, 2.98863746e+03, 2.11794100e+02, 1.02241467e+04, np.NaN,np.NaN, 9.00081968e+02, 2.52456745e+04, 1.50000000e+01],
[1.00000000e+00, 2.80583577e+03, 4.66145720e+02, 6.05642671e+03, np.NaN, np.NaN, 8.27249728e+02, 2.26365501e+04, 1.50000000e+01],
[2.00000000e+00, 5.28702810e+02, 3.30889610e+02, 5.10632793e+03, np.NaN, np.NaN, 6.03337243e+03, 6.52702811e+04, 1.50000000e+01],
[3.00000000e+00, 3.56128350e+02, 1.38663730e+02, 3.37923885e+03, np.NaN, np.NaN, 6.43263261e+03, 6.14788766e+04, 1.50000000e+01],
[4.00000000e+00, 9.10148200e+01, 8.30057400e+01, 4.31205993e+03, np.NaN, np.NaN, 7.63955009e+03, 6.08925862e+04, 1.50000000e+01]])
Particle.TrackID = 0
particles = np.vectorize(Particle)(*data.transpose())
l = [p.new_track_id for p in particles]
奇怪的是,ree_seeder 函数“print(self.new_track_id)”中的 print 语句,它会打印 0、1、2、3、4、5。
如果我随后取出粒子对象并从它们的 new_track_id 属性“l = [p.new_track_id for p inparticle]”中列出一个列表,则值为 1、2、3、4、5。
所以在某个地方,不知何故,第一个对象要么丢失,要么被重写,要么我不明白。
【问题讨论】:
-
不确定这是否更快但更简单:
dog_list = [Dog(*row) for row in dogs] -
更好
[Dog(*x) for x in dogs.tolist()] -
谢谢,这些至少应该让我的代码更干净!
-
向量化类构造函数给你另一个提升:
dog_list = np.vectorize(Dog)(*dogs.transpose()) -
@Jeronimo 天哪,这只是将我的代码从 50 秒加速到 1.3 秒:D 非常感谢!
标签: python-3.x pandas numpy oop vectorization