Problem mit indizieren von array / matrix

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
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

Hallo Leute!

Ich lese aus einer Text Datei (zunächst noch eine Liste) Koordinaten ein.
Jede Zeile steht für 3Punkte; die ersten drei pos. für x/y/z Werte; pos. 4. für Interaktionsenergie.

Ich möchte auf die oeinzelnen Werte zugreifen(die Summe von jew. der Interaktion einer Reihe bilden ;also jew. Pos 4).
Im nächsten Schritt will ich die Distanzen zwischen den Punkten berechnen (als Euklid Dist.).

Nur kann ich leider nicht auf die einzelnen Elemente zugreifen.

Liste nach einlesen:
[

Code: Alles auswählen

'([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990])', '([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.748, 0.650, 52.140, 11.990])', '([-0.068, 2.650, 53.140, 12.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])', '([-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])']
mein code:

Code: Alles auswählen

def euklid(new):
	
	laenge=len(new)
	print laenge, "moegliche Kombinationen" #Items der Liste
	
	print new
	
	
	for i in new:
		
		print i
		print "\n"
		
		#content = matrix(i)		 #jeder 3er array -> matrix
		content =array(i)
		
		
		print content
		print "\n"
		
		A= content[:,3]
		print A
		
		##summe_energie = sum(content)
		##print summe_energie
		##print "\n"
Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "oneforall1611a.py", line 185, in <module>
    new_vector    = euklid(new)
  File "oneforall1611a.py", line 104, in euklid
    A= content[:,3]
IndexError: 0-d arrays can only use a single () or a list of newaxes (and a single ...) as an index
Das Printen des Arrays funktioniert schonmal:

Code: Alles auswählen

([-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])
nur kann ich hier auf die pos 4 zugreifen....

(Wieviel dimensional ist mein Array eigentlich?)

Wenn ich das ganze als Matrixvariante durchführe:
item vor Matrix Umwandlung:

Code: Alles auswählen

([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.748, 0.650, 52.140, 11.990])
danach:

Code: Alles auswählen

[[ -0.392  -4.35   52.14   11.99   -0.678   0.65   54.14    9.99   -0.748
    0.65   52.14   11.99 ]]
hier kann ich natürlich nicht auf die letzte Spalte zugreifen.

:evil: :o :evil:

Hoffe, es kann mir jemand helfen!
Besten Dank!
BlackJack

Vergiss endlich mal Deine Abneigung gegen Fliesskommazahlen. Nach dem einlesen hast Du eine Liste mit *Zeichenketten*. Damit kann man *nicht* rechnen!

Schau mal was passiert:

Code: Alles auswählen

In [431]: a
Out[431]:
['([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990])',
 '([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.748, 0.650, 52.140, 11.990])',
 '([-0.068, 2.650, 53.140, 12.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])',
 '([-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])']

In [432]: b = numpy.array(a[0])

In [433]: b[:,3]
---------------------------------------------------------------------------
<type 'exceptions.IndexError'>            Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.IndexError'>: 0-d arrays can only use a single () or a list of newaxes (and a single ...) as an index

In [434]: b
Out[434]:
array('([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990])',
      dtype='|S99')
Das wo Du eine Fehlermeldung bekommst ist ein Array das genau *eine* Zeichenkette enthält. Ganz bestimmt nicht das was Du willst.
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

okay - nur wie kann ich in floats umwandeln (eine Liste habe ich zwangsweise durch das Auslesen der text Datei via readlines)?

Code: Alles auswählen

for i in new:                       #noch Liste
		
		floats=float(i)
		
		print floats
		print "\n"
bekomme ich als Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "oneforall1611a.py", line 191, in <module>
    new_vector    = euklid(new)
  File "oneforall1611a.py", line 99, in euklid
    floats=float(i)
ValueError: invalid literal for float(): ([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990])
Ferner wäre wichtig, dass ich die Info der drei Punkte behalte.

Danke!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Die Frage ist eigentlich eher: warum stehen sie so in der Datei drinnen?

Klar, du kannst auch diesen String in eine Liste von float-Werten umwandeln, aber geschickter wäre es, die Daten so in die Datei abzuspeichern, dass sie einfacher einlesbar sind. Also etwa mit `pickle`.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

Selbst wenn ich die datei mit pickle abspeichere/ wieder einlese,
geht an meiner Liste geht leider kein Weg vorbei. Nachdem ich die einzelnen Punkte aus der Datei eingelesen habe, bilde ich alle alle möglichen 3 Punkt Kombinationen über:


Code: Alles auswählen

def pharmakophor(inhalt):
	points = list(inhalt)
	kombinationen =[]
	print len(points)
	
	while points:
		item =points.pop(0)
		for x in points:
			for y in points:
				f (x<y):
					kombinationen.append([item, x, y]) 
Wie kann ich danach wieder in array/ matrix oder irgendwas umwandeln UND auf die entsprechenden Elemente zugreifen?

Danke!
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Es gibt viele Rezepte, um effizient zu permutieren. Schau mal hier: http://aspn.activestate.com/ASPN/Python/Cookbook/
Entscheidend ist oftmals einen generator zu verwenden. Bei der Zahl der Punkte in Deinem Beispiel geht es auch noch ohne. Aber die Komplexität Deines Algorithmus soll N^2 sein. Deine Funktion pharmakophor gibt eine Liste zurück, die ggf. extrem groß werden kann - und außerdem ist die Bennung der Funktion seltsam: pharmakophor = Permutationen? Über Funktionalität und Effizienz will ich gar nicht reden ...

Deine letzte Frage verstehe ich auch wieder nicht: Wenn Du ein numpy.array hast, kannst Du doch ohne weiteres wie bei Listen auch indizieren? Ggf. würde ich aber in der Datenstruktur die Koordinaten von dem Energiewert trennen - das könnte das Leben einfacher machen. ;-)

Gruß,
Christian
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

NB Vielleicht ist dieser Thread für Dich interessant?
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

@CM
Die Listen werden tatsächlich ziemlich lang: um 300.000 Hits.

Permutation ist es bei mir nicht - ich will jeden Punkt nur einmal haben:
(A/B/C), (D/E/F)....

nicht (B/A/C); (C/A/B)....

Um die gesamte Punktinfo zu behalten, muss ich die Energiewerte behalten. Ich will aus der Drei-Punkt-Info eine Matrix bauen mit der ich die Euklid Dist.berechnen/die Energie summieren kann - Umwandlung klappt, die Indizierung des "umgewandelten arrays /matrix aber nicht. s.o
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

acidk hat geschrieben: nicht (B/A/C); (C/A/B)....
Klar, sorry.
acidk hat geschrieben: Um die gesamte Punktinfo zu behalten, muss ich die Energiewerte behalten. Ich will aus der Drei-Punkt-Info eine Matrix bauen mit der ich die Euklid Dist.berechnen/die Energie summieren kann - Umwandlung klappt, die Indizierung des "umgewandelten arrays /matrix aber nicht. s.o
Klappt? Zeig' doch mal den Istzustand des arrays (bzw. einen Teil daraus).
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

Code: Alles auswählen

([-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])
Der restliche Code /Matrix /Array Varianten....usw. weiter oben :D :D :D
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Ja, das hast Du schon gezeigt - aber dann wieder von array gesprochen. Von Dimensionalität würde ich hier gar nicht sprechen, es ist ein tuple mit Listen.

Deine Funktion pharmakophor wird gar nichts zurückgeben, sie ist fehlerhaft. Ich verstehe immer noch nicht was sie genau machen soll (vielleicht bin ich zu blöd?), aber ich rate mal:

Code: Alles auswählen

from math import sqrt

def pharmakophor(inhalt):
    for x in inhalt:
        for y in inhalt:
            yield x,y

t = ([-0.392, -4.350, 52.140, 11.990], [-0.678, 0.650, 54.140, 9.990], [-0.748, 0.650, 52.140, 11.990])

total = 0

for kombi in pharmakophor(t):
   dist = sqrt((kombi[0][0]-kombi[1][0])**2 + 
	       (kombi[0][1]-kombi[1][2])**2 +
	       (kombi[0][2]-kombi[1][1])**2)
   print dist
   # nächste Zeile ich völlig geraten,
   # denn ich habe die Frage nicht verstanden
   total += kombi[0][3] + kombi[1][3]
Was ist das Problem mit der Indizierung?
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

Mein Ansatz so far.....

Text file, das ich auslese enthält die Koordinaten a la:

Code: Alles auswählen

-0.068, 2.650, 53.140, 12.990
-0.392, -4.350, 52.140, 11.990
-0.678, 0.650, 54.140, 9.990
-0.748, 0.650, 52.140, 11.990
usw....

Code: Alles auswählen

from numpy import*
import os

def find_files():
	
	temp = os.listdir(os.curdir)			      
	filenames =[name for name in temp if '.kont' in name] #Name d. auszulesenden Datei im Ordner!
	
	
	print filenames #Kontrolle der vorh. Files
	
	for i in filenames:
		
		datei = file(i,'r')
		
		inhalt = datei.readlines()
		
		datei.close
		
	print len(inhalt), "enthaltene Punkte"		
	return inhalt

def pharmakophor(inhalt):
	
	points = list(inhalt)
	kombinationen =[]
	print len(points)
	
	while points:
		item =points.pop(0)
		for x in points:
			for y in points:
				if (x<y):
					kombinationen.append([item, x, y])
	
	#print kombinationen
	return kombinationen

def reparse(kombinationen):
	new =[]
	 for i in kombinationen:             #Einzelelement ist noch ein Tuple!
		
		result  = str(i)                  #Umformung in String!
		
		result2 = result.replace("n'","]").replace("'","[").replace("\]","]")
		result3 = result2.replace("[[","([").replace("]]","])")
		
		new.append(result3)		   
		print type(new)
         print new[1]

#Hauptprgramm

inhalt  = find_files()
kombinationen = pharmakophor(inhalt)
new  = reparse(kombinationen)

#

Mit findfiles() lese ich die Datei aus.
Mit pharmakophor bekomme ich alle drei Punkt Kombis.
Reparse soll den ganzen string Müll beseitigen.... am Ende habe ich eine Liste mit den drei Punkten auf die ich auch "3Punktweise zugreifen kann!

-> print new [1] liefert:

Code: Alles auswählen

([-0.068, 2.650, 53.140, 12.990], [-0.392, -4.350, 52.140, 11.990], [-0.748, 0.650, 52.140, 11.990])
->ist aber wieder eine Liste aus strings... die ich umkonvertieren will---nur wie --- und in was!!!
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Ist das ein Anfang?

Code: Alles auswählen

import glob
import numpy
from math import sqrt

class Data:
    def __init__(self, coord, energy):
        # ggf. testen ob coord ein array ist
        self.coord = coord
        self.energy = energy
    def __repr__(self):
        return 'energy: ' + str(self.energy) + ' at ' + str(self.coord)

    def distance(self, other):
        return sqrt(sum((self.coord - other.coord)**2))

def extract(files):
    data = list()
    for fname in files:
        inf = open(fname)
        for line in inf:
            coords = numpy.array([float(x) for x in line.split(',')][:3])
            energy = float(line.split(',')[-1])
            data.append(Data(coords, energy))
        inf.close()
    return data

def combis(data):
    for n, x in enumerate(data):
       for y in data[n+1:]:
          yield x, y

if __name__ == "__main__":
    files = glob.glob('*.kont')
    data = extract(files)
    for combi in combis(data):
       print combi
Wozu ist reparse gut? Ich dachte der Punkt wäre längst geklärt? Das Snippet funktioniert natürlich nur, wenn Du wirklich nur Zahlen in der Datei hast und nicht irgendwelche Sonderzeichen neben dem Komma. Außerdem ist es natürlich nicht sehr *räusper* sophisticated.

HTH

Gruß,
Christian
acidk
User
Beiträge: 75
Registriert: Samstag 6. Januar 2007, 18:54
Wohnort: Braunschweig

Vielen DanK !!!!
:roll: ...sophisticated is das alles noch nicht so richtig... :oops:
Antworten