2017-05-26 3 views
2

Ich habe ein Dateiformat wie im folgenden Beispiel, das die Beziehungen zwischen 5 Personen einschließlich sich selbst zeigt.Konvertieren Sie eine 3-Spalten-Datei in das Matrixformat

1 1 1.0 
2 1 0.5 
3 1 0.1 
4 1 0.3 
5 1 0.1 
2 2 1.0 
3 2 0.5 
4 2 0.2 
5 2 0.3 
3 3 1.0 
4 3 0.5 
5 3 0.3 
4 4 1.0 
5 4 0.1 
5 5 1.0 

Ich möchte AWK verwenden, um es in ein vollständiges Matrixformat zu konvertieren. Ich müsste die Zeilen und Spalten wie im Beispiel numerisch sortiert haben.

1 2 3 4 5 
1 1.0 0.5 0.1 0.3 0.1 
2 0.5 1.0 0.5 0.2 0.3 
3 0.1 0.5 1.0 0.5 0.3 
4 0.3 0.2 0.5 1.0 0.1 
5 0.1 0.3 0.3 0.1 1.0 

Ich kam in einem früheren Thread (unten), aber das Format der Eingabedatei ist etwas anders, und ich kämpfen, um es zu ändern. http://www.unix.com/shell-programming-and-scripting/203483-how-rearrange-matrix-awk.html

Wie kann ich diese Transformation durchführen?

+0

Sind die Tasten "A" bis "E" repräsentativ für die in Ihren echten Daten? Ist es erforderlich, dass sie in der Ausgabe alphabetisch sortiert sind? –

+0

Die realen Werte von A bis E sind numerisch (10 bis 13 Ziffern) und ja, es wäre erforderlich, dass sie numerisch sortiert sind. – roddy

+0

OK, das sind nützliche Informationen, also sollte es in Ihre Frage eingehen. Möglich [edit] um auch dein Beispiel zu aktualisieren, also werden Nummern anstelle von Buchstaben verwendet (sie müssen natürlich nicht so viele Ziffern enthalten!). –

Antwort

2

Hier gehen wir, gaffen Lösung:

matrixize.awk Skript:

#!/bin/awk -f 
BEGIN { OFS="\t" }  # output field separator 
{ 
    b[$1];    # accumulating unique indices 
    if ($1 != $2) { 
     a[$2][$1] = $3 # set `diagonal` relation between different indices 
    } 
    a[$1][$2] = $3  # multidimensional array (reflects relation `one-to-many`) 
} 
END { 
    asorti(b); h = ""; # sort unique indices 
    for (i in b) { 
     h = h OFS i  # form header columns 
    } 
    print h;   # print header column values 
    for (i in b) { 
     row = i;  # index column 
     # iterating through the row values (for each intersection point) 
     for (j in a[i]) { 
      row = row OFS a[i][j] 
     } 
     print row 
    } 
} 

Nutzungs:

awk -f matrixize.awk yourfile 

Der Ausgang:

1 2 3 4 5 
1 1.0 0.5 0.1 0.3 0.1 
2 0.5 1.0 0.5 0.2 0.3 
3 0.1 0.5 1.0 0.5 0.3 
4 0.3 0.2 0.5 1.0 0.1 
5 0.1 0.3 0.3 0.1 1.0 
+0

Hallo danke dafür. Es lief, aber ich scheine eine andere Reihenfolge für die IDs zu bekommen, was du hast? Die Eingabedatei wurde wie von Ihnen angegeben als Tabulator getrennt. 1,0 \t 0,1 \t 0,3 \t 0.2 \t 0,5 0,1 \t 1,0 \t 0,1 \t 0,3 \t 0,3 0,3 \t 0,1 \t 1,0 \t 0,5 \t 0,1 0,2 \t 0,3 \t 0,5 \t 1,0 \t 0,5 0,5 \t 0,3 \t 0,1 \t 0,5 \t 1.0 – roddy

+0

@roddy, ich habe die Eingabe von Ihrer Frage verwendet, wie es ist. Und ich erhalte die erwartete Ausgabe (als Ihre gewünschte Ausgabe). Überprüfen Sie, ob Ihre Datei führende Leerzeichen/Tabs (vor der ersten Spalte) hat. – RomanPerekhrest

1

als oberes und unteres Dreieck identisch ist, wäre es nicht genug sein, um jedes Element-Paar zu beiden Indizes in einem mehrdimensionalen Array zu kopieren, zum Beispiel:

parse.awk

{ h[$1,$2] = h[$2,$1] = $3 } 

END { 
    for(i=1; i<=$1; i++) { 
    for(j=1; j<=$2; j++) 
     printf h[i,j] OFS 
    printf "\n" 
    } 
} 

Run:

awk -f parse infile 

Ausgang:

1.0 0.5 0.1 0.3 0.1 
0.5 1.0 0.5 0.2 0.3 
0.1 0.5 1.0 0.5 0.3 
0.3 0.2 0.5 1.0 0.1 
0.1 0.3 0.3 0.1 1.0 

Beachten Sie, dass dies die letzte Zeile geht davon hält die größte Indizes.

+0

Thor, Die oberen und unteren sind identisch, ich kann beide Methoden verwenden. Ich werde sie beide jetzt in einer großen Datei (9.000 x 9.000) testen und sehen, welche schneller ist. Wie immer danke an alle für die Hilfe. – roddy

+0

Nachdem ich den Code in meinem realen Datensatz getestet habe, sieht es so aus, als müsste die Nummerierung der IDs von 1 aufwärts gezählt werden. – roddy

+0

Hallo, nachdem Sie den Code in einem echten Dataset getestet haben, sieht es so aus, als müsste die Nummerierung der IDs von 1 aufwärts beginnen. Meine echten IDs beginnen bei einer achtstelligen Zahl, d. H. 62243121. Wie würde ich die Spalten 1 und 2 neu nummerieren, um bei 1 zu beginnen, aber sicherstellen, dass die Umnummerierung derselben ID in Spalte 1 dieselbe ist wie in Spalte 2? Danke nochmal, Roddy – roddy

Verwandte Themen