Frage zum Verhalten von Arrays

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
sirvival
User
Beiträge: 6
Registriert: Mittwoch 13. Juli 2011, 15:17

Hi,
ich bin heute über etwas gestolpert dass ich nicht ganz verstehe.

Ich lese einen Datensatz von 26 Zeilen mit je 300000 Einträgen ein.

Auf diesen möchte ich random noise legen.

Code in etwa:

Code: Alles auswählen

data_all = np.loadtxt(path1+"data_all.dat")

data_noise = data_all

for i in range(26):
	data_noise[i] += np.random.normal(0,1e12,data_noise[0].size)
Wenn ich mir nun beides plotte (also data_all und data_noise) sind beide identisch.

Habe ich aber statt
data_noise = data_all
data_noise = data_all.copy()
im code stehen dann bleibt data_all ohne noise erhalten.

Wieso ist bei variante 1 data_all mit data_noise verbunden (weiß jetzt nicht wie ich dass Ausdrücken soll)?
Ich dachte so etwas kommt bei python nicht vor.


Gruß

PS: benutze python 2.7.1

Beispiele zum Verdeutlichen (ihr habt ja nicht meine Daten):
Var1

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as mpl

data_all = np.zeros(100)

data_noise = data_all

data_noise += np.random.normal(0,1e12,data_noise.size)

mpl.plot(data_all,'r-',label='Original Data')
mpl.plot(data_noise,'b-',label='With Noise')
mpl.legend()
mpl.show()
Var2

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as mpl

data_all = np.zeros(100)

data_noise = data_all.copy()

data_noise += np.random.normal(0,1e12,data_noise.size)

mpl.plot(data_all,'r-',label='Original Data')
mpl.plot(data_noise,'b-',label='With Noise')
mpl.legend()
mpl.show()
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Soviele Beispiele wären gar nicht nötig gewesen ...

Die Lösung ist einfach. Die Zuweisung

Code: Alles auswählen

neuliste = alteliste
liefert dir keine Kopie von alteliste, sondern eine Referenz, d.h. einen weiteren Namen auf exakt die gleiche Liste, die du nun sowohl über alteliste als auch über neueliste ansprechen kannst.
Für eine einfache Kopie genügt auch:

Code: Alles auswählen

neuliste = alteliste[:]
sirvival
User
Beiträge: 6
Registriert: Mittwoch 13. Juli 2011, 15:17

Ist dies immer so mit der Referenz?
Meine ich habe dass schon einmal so gemacht ohne Problem (also a=b).


Gruß
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ja, es werden immer die Referenzen verwendet. Wahrscheinlich ist es dir bisher noch nicht aufgefallen, weil es (nach außen) bei unveränderlichen Typen, wie Tupel, Zahlen oder Strings, keinen Unterschied macht, ob man mit Referenzen oder Kopien arbeitet.

Sebastian
Das Leben ist wie ein Tennisball.
BlackJack

@numerix: Der OP arbeitet mit `numpy`-Arrays, da hat ”slicing” nicht den gewünschten Effekt ein unabhängiges Objekt zu erzeugen:

Code: Alles auswählen

In [62]: a = np.zeros((3, 3))

In [63]: b = a[:]

In [64]: b += 1

In [65]: a
Out[65]: 
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

BlackJack hat geschrieben:@numerix: Der OP arbeitet mit `numpy`-Arrays, da hat ”slicing” nicht den gewünschten Effekt ein unabhängiges Objekt zu erzeugen:
Danke für die Korrektur.
sirvival
User
Beiträge: 6
Registriert: Mittwoch 13. Juli 2011, 15:17

Hi,
eines verstehe ich aber noch nicht ganz:

Code: Alles auswählen

import numpy as np
a = np.zeros(10)
b = a
b = b+1
print a,b
[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.] 
[ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]
vs

Code: Alles auswählen

import numpy as np
a = np.zeros(10)
b = a
b += 1
print a, b
[ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]
[ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]
Der + Operator arbeitet also ohne Ref. und += mit?


Gruß und Danke


PS: komme von IDL kenne dort keinen entsprechenden += Operator
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Nein, in beiden Fällen wird weiter mit Referenzen gearbeitet. Allerdings erzeugt `+` ein neues Array `+=` hingegen verändert das aktuelle. Vielleicht hilft dir der folgende Code beim Verständnis ein wenig weiter:

Code: Alles auswählen

>>> spam = [1,2,3]
>>> eggs = [4,5,6]
>>> id(spam)
140297289139552
>>> id(eggs)
140297288982400
>>> foo = spam+eggs
>>> id(foo)
140297289041176
>>> spam += eggs
>>> spam
[1, 2, 3, 4, 5, 6]
>>> id(spam)
140297289139552
>>> eggs
[4, 5, 6]
>>> id(eggs)
140297288982400
Das Leben ist wie ein Tennisball.
sirvival
User
Beiträge: 6
Registriert: Mittwoch 13. Juli 2011, 15:17

Alles klar!
Vielen Dank

Gruß und schönes Wochenende
Antworten