2012-07-05 10 views
6

Sütunların farklı veri türleri içerdiği numpy.array s var ve sütunlar da farklı işlevlere sahip olmalıdır. Bir dizide de fonksiyonlar var.Numpy: Aynı uzunlukta 2d-array değeri ile elemansal olarak çarparak bir fonksiyon dizisi uygulayın. (Operatör olarak bir python işlevi mi kullanıyorsunuz?)

Diyelim ki:

a = array([[ 1, 2.0, "three"], 
      [ 4, 5.0, "six" ]], dtype=object) 

functions_arr = array([act_on_int, act_on_float, act_on_str]) 
kesinlikle şeyi bölerek bunu yapmak yollar geliyor

, ama bana yayın ile elementwise çarpma olarak düşünmek etmektir için en doğal görünüyor tek şey, ve işleçler olarak işlevler. O yüzden bu satırlar boyunca bir şey elde etmek için bir yol biliyor musunuz

array([[act_on_int(1), act_on_float(2.0), act_on_str("three")], 
     [act_on_int(4), act_on_float(5.0), act_on_str("six") ]]) 

etkisini

functions_arr*a 

böyle bir şey yapmak ve almak istiyorum?

Düzenleme: insanlar dizi tipleri ben amaçlanan şekilde saklamak için bu önemlidir belirttiği gibi ben dtype=[object] içerecek şekilde söz konusu dizinin tanımını değiştirdi.

Yanıtlarınız ve yorumlarınız için teşekkür ederiz! Gönderenleri yanıtlamayı kabul ettim ve bunun aklımdakilere çok yakın olduğunu hissediyorum. Ameliyat düşünün nasıl bir karışıklık, çarpma gibi olmak bana başka örnekle açıklığa kavuşturmak izin olmuştur görünüyor yana

:

Farkında gibi, benzeri bir operasyon:

v = array([1,2,3]) 
u = array([[5,7,11], 
      [13,17,19]]) 
v*u 

u sıraları üzerinde v yayın yapacak ve

array([[ 1*5, 2*7, 3*11], 
     [1*13, 2*17, 3*19]]) 

yani

01 verir Şimdi biz olurdu mesela del operator için birlikte v yerine olsaydı
array([[ 5, 14, 33], 
     [13, 34, 57]]) 

(aşağıdaki aslında piton kodunu :)

V = array([(d/dx),(d/dy),(d/dz)]) 
u = array([[5,7,11], 
      [13,17,19]]) 
V*u 

ruhu içinde (elde)

çalışma değil olduğunu
array([[(d/dx)5, (d/dy)7, (d/dz)11]], 
     [(d/dx)13,(d/dy)17,(d/dz)19]]) 

Bir demet sabitin türevini kabul etmeyeceğimi itiraf ediyorum. operasyonların ilginç, bu yüzden x, y ve z bazı sembolik matematiksel ifadesi ile u değiştirmek için çekinmeyin. Her halükarda, en azından bu konudaki gerekçelendirme (“bir python işlevini operatör olarak kullanma”) konusundaki mantığım ve netliği daha da açık bir şekilde ortaya koyarım.

cevap

2

, oluşturduğunuz dizisi muhtemelen Python nesne bir dizidir. Üzerinde herhangi bir işlem muhtemelen numpy işlemlerinden çok daha yavaş olacaktır. Ancak, gerçekten çok hızlı olmanızı beklemediğiniz sürece oldukça kolay bir şekilde istediklerinizi yapabilirsiniz! Bu AFoglia önerdi çok farklı değildir, ama sizin için sorulan tam olarak ne olmak daha yakın: Ayrıca bir rekor dizisi kullanarak daha iyi olurdu iyi bir şans var, burada AFoglia yankılanan

>>> a = numpy.array([[ 1, 2.0, "three"], 
...     [ 4, 5.0, "six" ]], dtype=object) 
>>> funcs = [lambda x: x + 10, lambda x: x/2, lambda x: x + '!'] 
>>> apply_vectorized = numpy.vectorize(lambda f, x: f(x), otypes=[object]) 
>>> apply_vectorized(funcs, a) 
array([[11, 1.0, three!], 
     [14, 2.5, six!]], dtype=object) 

- Bu veriyor Eğer istediğiniz gibi diziyi bölmek ve ufuncs numpy kullanarak daha doğal bir şekilde onunla çalışmak - Python fonksiyonları çok daha hızlı olan, genellikle:

rec.array([(1, 2.0, 'three'), (4, 5.0, 'six')], 
     dtype=[('int', '<i8'), ('float', '<f8'), ('str', '|S10')]) 
>>> a['int'] 
array([1, 4]) 
>>> a['float'] 
array([ 2., 5.]) 
>>> a['str'] 
rec.array(['three', 'six'], 
     dtype='|S10') 
>>> a['int'] += 10 
>>> a['int'] 
array([11, 14]) 
3

Eğer lists kullanarak yerleşik fonksiyonu zip()

Basit bir örnek arıyorsanız: Orijinal dizisi sadece bir boyutunu vardı çünkü yayın değil

>>> a=[[ 1, 2.0, "three"],[ 4, 5.0, "six" ]] 

>>> funcs=[lambda x:x**2,lambda y:y*2,lambda z:z.upper()] 

>>> [[f(v) for v,f in zip(x,funcs)]for x in a] 
[[1, 4.0, 'THREE'], [16, 10.0, 'SIX']] 
+3

Bu sorunun cevabının sanmıyorum. OP bu durumda nasıl yayın yapılacağını sordu. Bu kod yayın yapmıyor. –

3

. Her öğenin üç üyesi (int, float ve dize) olduğu için 2 boyutuna sahip olduğu anlaşılıyor, ancak numpy için, bu basitçe tür ve boyutların sayısı birdir.

Bu, çarpım da değildir, çünkü işlevi her bir öğeye uygularsınız. (functions_arr * a, yanıltıcı sözdizimidir.)

Yine de, istediğiniz şeye benzer bir şey yazabilirsiniz. Numpy.vectorize deneyebilirim. Test edilmeden ve çıkış dtipinin orijinal dizi ile aynı olduğunu varsayarak. Ben

def act_on_row(row) : 
    return (act_on_int(row["int_field"]), 
      act_on_float(row["float_field"]), 
      act_on_str(row["str_field"])) 

act_on_array = numpy.vectorize(act_on_row, otypes=[a.dtype]) 

acted_on = act_on_array(a) 

... nasıl olacağını hayal ben vectorize hiç denemedim ve yapılandırılmış dtypes ile çalışan almak zor olmadığını bilmiyorum, ama bu başlangıç ​​almalısınız.

Ancak daha basit olan çözüm, dizinin alanın üzerine eklenmesidir.

rslt = numpy.empty((len(a),), dtype=a.dtype) 

rslt["int_field"] = act_on_int(a["int_field"]) 
rslt["float_field"] = act_on_float(a["float_field"]) 
rslt["str_field"] = act_on_str(a["str_field"]) 

(Ne yaptıklarını bağlı olarak her bireyin fonksiyonu vektörize gerekebilir.) Sven Marnach bana hatırlattığı gibi

+1

Orijinal gönderide tanımlanan "a" dizisi iki boyutlu bir dizidir ve * tek boyutlu bir yapılandırılmış dizi değildir. (OP * 'nin aslında yapılandırılmış bir dizi kullanması gerektiğini iddia edebilirsiniz.) –

+0

@SvenMarnach, doğru; ama heterojen veri türleri ile gerçek 2 boyutlu bir diziye sahip olmak bile _possible_? Bu cevapta bir varyasyon önereceğim, ancak OP'nin yarattığı iddiaları nasıl yaratacağımı anlayamadım. Bu amaçla sadece yapısal/kayıt dizileri kullandım. – senderle

+1

@senderle: OP tarafından verilen kodun sadece bir dizi sabit genişlikli dizeler oluşturacağını düşünüyorum. Dizi öğeleri olarak rasgele Python nesnelere izin veren 'dtype = object' kullanarak heterojen bir dizi oluşturabilirsiniz. Bununla birlikte, bu, NumPy'nin performans ve bellek faydalarının çoğunu geçersiz kılacaktır - bu tür diziler çok boyutlu, sabit boyutlu Python listeleri olarak tanımlanabilir. –

İlgili konular