File lesen & Mean berechnen < Matlab < Mathe-Software < Mathe < Vorhilfe
|
Status: |
(Frage) beantwortet | Datum: | 20:20 Mi 29.11.2006 | Autor: | Leoni |
Hallo,
vorweg: Ich bin noch ziemlich neu, was das Programmieren betrifft, und wurde vor eine Aufgabe gestellt, die mir unloesbar scheint :-/. Ich bin fuer jeden noch so kleinen Tipp sehr dankbar! Danke schon mal im Voraus Ich schreibe deshalb mein Problem von Anfang an auf, da ich vielleicht schon den falschen Ansatz beim Dateneinlesen habe.
Ich muss zuerst eine .txt Datei einlesen mit folgender Struktur:
01 1 3 15.44 1 1 2 2 744.2 1014.9 K1 K1
01 1 3 15.44 1 2 2 2 456.9 672.1 K1 K1
01 1 3 15.44 1 3 2 2 344.0 685.2 K1 K1
01 1 3 15.44 4 4 2 2 768.3 696.5 K4 K4
01 1 3 15.44 4 5 2 2 3563.3 677.5 K4 K4
01 1 3 15.44 3 6 2 2 565.3 778.0 K4 K4
01 1 3 15.44 1 7 2 2 655.8 764.2 K1 K1
01 1 3 15.44 3 8 2 2 222.8 1595.1 K4 K4
01 1 3 15.44 3 9 2 2 555.5 759.4 K4 K4
...
Ziel ist es, die Daten aus Spalte 9 zusammenzufassen zu mehreren Mittelwerte. Vereinfacht auf folgende Weise: In Abhaengigkeit ob eine Zeile eine Wiederholung in Spalte 5 zur vorangehenden Zeile darstellt. D.h. ein Mittelwert der Zahlen in Spalte 9 fuer alle Wiederholungen in Spalte 5 (in diesem Fall waere das: Mean_Wiederholung_Spalte5=(Zeile2+Zeile3+Zeile5+Zeile9):4) und Mean_Nicht_Wiederholung_Spalte5=(Zeile4+Zeile6+Zeile7+Zeile8):4)
=> Da die erste Zeile keinen "Vorgaenger" hat, muss diese von der Mittelwertbildung ausgeschlossen werden.
Mein Ansatz (s.u.) reicht bisher nur soweit, dass ich eine Datei einlesen kann, und in Abhaengigkeit von der Zahl in einer Spalte, eine andere Spalte mitteln kann. Also ich habe noch ueberhaupt keine Idee, wie ich auf die vorherige Zeile verweisen kann (und somit auch Wiederholungen einer Zahl feststellen kann). Falls mir hierzu jemand einen Tipp haette, waer das klasse!
%%% this is my script to read my data files
fname = input('Enter the file name ') %% prompt the user for a filename
fid = fopen(fname) %% open the file and get a file ID
for i=2:16
fline = fgets(fid) %% read a line of the file
switch fline(16) %% switch loop based on the number in the 16th column
case '1'
R-l-c(i) = str2num(fline(25:29)); %% read number
case '2'
R-r-c(i) = str2num(fline(25:29)); %% read number
case '3'
R-l-w(i) = str2num(fline(25:29)); %% read number
case '4'
R-r-w(i) = str2num(fline(25:29)); %% read number
end
end
R-left-c = R-l-c ~=0 ; %raus mit den Nullern aus Vektor
R-right-c = R-r-c ~=0 ;
R-left-w = R-l-w ~=0 ;
R-right-w = R-r-w ~=0 ;
Mean-R-left-c=mean(R-l-c(R-left-c))
Mean-R-left-w=mean(R-l-w(R-left-w))
Mean-R-right-c=mean(R-r-c(R-right-c))
Mean-R-right-w=mean(R-r-w(R-right-w))
fclose(fid) %% close the file
Wie gesagt, jeder noch so kleiner Tipp, kann mir eine grosse Hilfe sein!
Gruss
Leonie
Ich habe diese Frage in keinem Forum auf anderen Internetseiten gestellt.
|
|
|
|
Hallo,
da mir nicht ganz klar ist, was du da genau mit den Daten machst, mache ich das mal allgemein:
Die Daten, die du in Spalte 9 hast (von den Nullen vorher bereinigt, falls nötig), seien mal in Vektor data abgelegt und die Daten aus Spalte 5 seien im Vektor indices abgelegt.
Dann schlage ich Folgendes vor: Wir ziehen von dem um 1 verschobenen Datenvektor den ursprünglichen Datenvektor ab. Dann stehen Nullen an den Stellen mit Wiederholung und andere Zahlen an den Stellen ohne Wiederholung. Allerdings sind die Indizes um 1 verschoben:
wdh = (indices(2:end) - indices(1:end-1)==0); %enthält Nullen für Wdh., Einsen für keine Wdh.
data_tail = data(2:end); %Also lassen wir es weg...;
Mean_mit_Wdh = mean(data_tail(wdh));
Mean_ohne_Wdh = mean(data_tail(not(wdh)));
Klar, oder?
Noch eine Anmerkung zum Einlesen:
Falls du die Struktur deiner Tabelle kennst, kannst du sie in einem Aufwasch einlesen. Mal angenommen, die ersten 4 Spalten enthalten numerische Daten, die nächsten beiden enthalten irgendwelche Strings, die du überspringen willst und die nächsten beiden enthalten wieder Daten. Dann geht es ganz schnell mit:
fid = fopen('Daten.txt');
daten = fscanf(fid,'%g %g %g %g %*s %*s %g %g', [6 inf])';
fclose(fid);
Dann kannst du die Daten gleich Spaltenweise verarbeiten,
Gruß
Martin
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 15:15 Do 30.11.2006 | Autor: | Leoni |
Hallo Martin,
vielen Dank, das war nicht nur ein kleiner Tipp, sondern die Loesung vom ganzen Problem! Auch das Dateneinlesen klappt auf diese Weise viel besser!
Ich hab noch eine weitere Frage zu diesem Problem: Einen anderen Datensatz muss ich aehnlich einlesen, und auf aehnliche Weise Mittelwerte berechnen. Nur diesmal noch etwas verzwickter. Daten sehen vereinfacht so aus (alles nach % ist schon meine Anmerkung zum Problem s.u.):
1 34.56 % (hat keine zwei Vorgaenger => muss ignoriert werden)
2 43.43 % (hat keine zwei Vorganeger => muss ignoriert werden)
4 34.22 % Wert 34.22 geht in Berechnung ein zu (Mean_124)
3 34.22 % Wert 34.22 geht in Berechnung ein zu (Mean_243)
4 44.22 % Wert 44.22 geht in Berechnung ein zu (Mean_434)
2 55.43 % Wert 55.43 geht in Berechnung ein zu (Mean_342)
2 23.23 % 23.23 (Mean_422)
2 23.23 % (Mean_222)
2 45.77 % (Mean_222)
3 56.87 % (Mean_223)
4 78.45 % (Mean_234)
2 45.56 % (Mean_342)
1 45.89 % (Mean_421)
4 32.45 % (Mean_214)
1 34.76 % (Mean_141)
2 45.78 % (Mean_412)
4 34.35 % (Mean_124)
1 35.78 % (Mean_241)
2 45.97 % (Mean_412)
...
Ziel ist es: Die Werte aus der 2. Spalte, in Abhaengigkeit von dem Wert in der 1. Spalte UND den beiden Vorgaengern in der 1. Spalte einzulesen. In der 1. Spalte gibt es nur die Werte 1,2,3 oder 4 (treten zufaellig nacheinander auf, unabhaengig vom Vorgaenger). D.h. Es gibt insgesamt 64 Moeglichkeiten, wie drei Zahlen der ersten Spalte aufeinander folgen koennen (4x4x4). Fuer jede dieser Moeglichkeit muss ich nun einen Mittelwert bilden, der Zahlen in Spalte 2 (fuer die genau diese 3er Abfolge zutrifft) => Am Ende 64 Mittelwerte.
In Anlehnung an deinen Tipp fuer mein erstes Problem, hab ich nun folgendes gemacht:
daten = fscanf(fid,'%g %g %g %g %*s %*s %g %g %g', [7 inf])'
data=daten(:,2)
indices=daten(:,1)
for i=1:5000
if indices(i)==1 & indices(i+1)==1 & indices(i+2)==1 % Abfolge 1 1 1
Data_for_Mean111(i)=daten(i+2)
elseif indices(i)==2 & indices(i+1)==2 & indices(i+2)==2 % Abfolge 2 2 2
Data_for_Mean222(i)=daten(i+2)
elseif indices(i)==3 & indices(i+1)==3 & indices(i+2)==3 % Abfolge 3 3 3
Data_for_Mean333(i)=daten(i+2)
elseif indices(i)==4 & indices(i+1)==4 & indices(i+2)==4 % Abfolge 4 4 4
Data_for_Mean444(i)=daten(i+2)
...
end
end
Das ergibt dann einen Vektor mit den Daten fuer jeden Mean, da muss ich noch die Nullen raus bekommen (fuer jeden Fall in dem die Abfolge nicht zutrifft, schreibt das Programm eine Null in den Mean_Vektor) und mitteln (ich denke, das ist nicht schoen, aber ok). Aber meine Frage: Kann man die drei Zahlen aus Spalte 1 auch irgendwie verknuepfen (concat?) und dann wuerde es vielleicht anders/einfacher gehen?
Gruss,
Leonie
|
|
|
|
|
Hallo,
das Konkatenieren von Zahlen ist so nicht möglich. Da müsste man sich schon eine schöne Kodierung für die Zahlenfolgen überlegen.
Falls du aber mit Matlab 7 arbeitest, dann gibt es eine recht einfache Lösung. Ich knalle dir erstmal den (zugegebenermaßen etwas langen) Einzeiler hin:
MeanMatrix = accumarray([indices(1:end-2) indices(2:end-1) indices(3:end)],data(3:end))./max(ones(4,4,4),accumarray([indices(1:end-2) indices(2:end-1) indices(3:end)],ones(size(data(3:end)))))
Die Mittelwerte für Indexfolgen (a,b,c) sind dann in der Matrix gespeichert und können direkt abgefragt werden. Für den Mittelwert der Daten bei der Indexfolge (2,1,4) geben wir ein:
MeanMatrix(2,1,4)
Probier es erstmal aus. Wenn es funktioniert, dann kann ich es dir erklären (falls du es nicht verstehst) und evtl. in kleinere Teile aufspalten.
Falls du eine ältere Matlab-Version verwendest, dauert es nur wenig länger. Hier kann man wirklich auf eine Kodierung zurückgreifen:
indices_code = 16*(indices(1:end-2)-1) + 4*(indices(2:end-1)-1) + (indices(3:end)-1);
for a=1:4, for b=1:4, for c=1:4,
matching_data = data([false;false;indices_code==16*(a-1)+4*(b-1)+(c-1)]);
MeanMatrix(a,b,c) = sum(matching_data)/max(1,size(matching_data,1));
end; end; end;
Falls du hierzu Fragen hast, auch bitte melden.
Gruß
Martin
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 21:50 Fr 01.12.2006 | Autor: | Leoni |
Hallo Martin,
vielen Dank fuer die schnelle Hilfe ... einfach klasse! Ich bastle noch etwas dran rum, aber muesste bald klappen. Danke!
Gruss,
Leonie
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 11:04 Mo 04.12.2006 | Autor: | Leoni |
Hallo,
noch eine Frage zum fscanf Befehl: Wenn ich eine der String Variabeln NICHT ignorieren will, sondern mit einlesen will, weil ich sie weiterverarbeiten moechte, geht das auch mit diesem Befehl? Es scheint nicht damit getan, den * wegzulassen ... Danke fuer die Hilfe!
Gruss,
Leonie
> fid = fopen('Daten.txt');
> 1: | daten = fscanf(fid,'%g %g %g %g %*s %*s %g %g', [6
| 2: | > inf])'; |
> fclose(fid);
>
|
|
|
|
|
Hallo,
hierfür brauchst du die textread-Funktion. Der Aufruf sähe dann z.B. so aus:
[zahlenspalte1, zahlenspalte2, stringspalte1, zahlenspalte3, zahlenspalte4]=textread('Daten.txt,'%f %*s %f %*s %s %f %f %*s', 'delimiter','\t')
Die einzelnen (nicht ignorierten) Spalten werden in den in der eckigen Klammer angegebenen Variablen abgelegt. Es müssen natürlich so viele Variablen angegeben werden, wie du Spalten einlesen möchtest.
Der String hinter 'delimiter' gibt das Trennzeichen der Spalten an, in diesem Fall den Tabulator.
Öffnen und Schließen der Datei übernimmt die Funktion.
Gruß
Martin
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 22:31 Mo 04.12.2006 | Autor: | Leoni |
Hallo Martin,
ok, super das klappt. Vielen Dank nochmal!
Gruss,
Leonie
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 11:55 Mi 06.12.2006 | Autor: | Leoni |
Hallo,
das klappt nun alles soweit. Danke noch mal fuer die Hilfe, einfach klasse! Hab noch eine Frage: Hab nun alle meine Werte in einer Matrix (zumindest auf dem Matlab-Ausgabebildschirm), und moechte diese in eine Datei schreiben. Die Matrix sieht wie folgt aus:
Matrix=
[M1,n1,s1,f1,k1;
M2,n2,s2,f2,k2;
M3,n3,s3,f3,k3;
M4,n4,s4,f4,k4;
...
M10,n10,s10,f10,k10]
Bzw. wie folgt:
581.3623 45.0000 0 0 0
989.3775 33.0000 0 0 0
541.9020 56.0000 0 0 0
479.3766 45.0000 0 0 0
770.1577 111.0000 1.0000 0 0
865.6468 87.0000 0 0 1.0000
890.5777 100.0000 0 0 4.0000
879.1662 77.0000 0 1.0000 2.0000
233.3459 104.0000 1.0000 0 1.0000
633.7215 103.0000 0 1.0000 1.0000
Am besten waer es, wenn die ertse Spalte Dezimal blieb, und die folgenden Spalten nur noch die ganzen Zahlen da staenden. Ich habe folgendes probiert (s.u), aber leider schreibt mir dieser Befehl alle Daten in eine Zeile! Weiss jemand wie ich die Matrix, als ebensolche auch in die Datei schreiben kann? Danke vielmals!
Gruss,
Leoni
fid = fopen('ergebnis.txt','w')
fprintf(fid,'%6.2f, %6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d [mm] \n',Matrix); [/mm] %
fclose(fid);
|
|
|
|
|
Hallo,
das geht erheblich kürzer!
Du musst nur eine Zeile formatieren, da alle das gleiche Format haben. In eine neue Zeile kommst du mit \n.
Komplett sieht das sos aus:
fid = fopen('ergebnis.txt','w');
fprintf(fid,'%6.2f, %d, %d, %d, %d\n',matrix'); %beachte das Apostroph! Transponierte Matrix!
fclose(fid);
Der Code für den Tabulator als Trennzeichen ist übrigens \t.
Gruß
Martin
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 15:45 Mi 06.12.2006 | Autor: | Leoni |
... fuer die super schnelle Hilfe, und es klappt
Gruss,
Leonie
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 11:51 Mo 11.12.2006 | Autor: | Leoni |
Hallo,
jetzt hab ich doch noch eine Frage: Das hat nun alles geklappt, und die Werte sind in einer .txt Datei. Problem ist, wenn ich diese Datei NICHT im Matlab Editor oeffne, dann stehen die Werte wieder alle in einer Zeile (und nicht in Spalten). Liegt das an meinem .txt Editor? Oder was mache ich falsch?
Danke
Gruss,
Leonie
|
|
|
|
|
Hallo,
das liegt an dem Editor. Windows und Unix-Betriebssysteme haben unterschiedliche Zeilenumbrüche und einige Windows-Editoren (nur die einfachsten wie Notepad) beherrschen das Unix-Newline \n nicht und zeigen an seiner Stelle ein Kästchen an.
Mit dem Wordpad sollten das gehen. Wenn du die Datei einmal mit Wordpad öffnest und wieder speicherst, wird der Zeilenumbruch auf Windows umgestellt und du kannst die Datei auch im Notepad öffnen.
Du kannst aber am Ende des Formatstrings in fprintf statt \n einfach \r\n angeben. Das sollte dem Windows-Zeilenumbruch entsprechen.
Gruß
Martin
|
|
|
|