So extrahieren Sie den Maximal- und Minimalwert aus Spalte 1 und Spalte 2

So extrahieren Sie den Maximal- und Minimalwert aus Spalte 1 und Spalte 2

Liebe alle, ich habe einegroßDatendatei sagen wir maldatei.datenthält es zwei Spalten

zB file.dat (zeigt wenige Zeilen)

    0.0000  -23.4334
    0.0289  -23.4760
    0.0578  -23.5187
    0.0867  -23.5616
    0.1157  -23.6045
    0.1446  -23.6473
    0.1735  -23.6900
    0.2024  -23.7324
    0.2313  -23.7745
    0.2602  -23.8162
    0.2892  -23.8574
    0.3181  -23.8980
    0.3470  -23.9379
    0.3759  -23.9772
    0.4048  -24.0156
    0.4337  -24.0532
    0.4627  -24.0898
    0.4916  -24.1254
note: data file has a blank line at the end of the file

Erwartete Ergebnisse

Ich möchte das Maximum und Minimum aus beiden Spalten finden/extrahieren, z. B. Spalte 1

max - 0.4916
min - 0.0000

ähnlich Spalte-2

max - -23.4334
min - -24.1254

Unvollständige Lösung (funktioniert nicht für Spalte 2)

Für Spalte-1

awk 'BEGIN{min=9}{for(i=1;i<=1;i++){min=(min<$i)?min:$i}print min;exit}' file.dat 
0.0000
cat file.dat | awk '{if ($1 > max) max=$1}END{print max}'
0.4916

für Spalte-2

awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
-23.4334

cat file.dat | awk '{if ($2 > max) max=$2}END{print max}'
**no output showing**

Problem

Bitte helfen Sie mir, den Minimal- und Maximalwert aus Spalte 2 zu finden Hinweis: Die Datendatei hat am Ende eine Leerzeile.

Antwort1

Das Problem in Ihrem Code,

awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat

... ist, dass Sie sofort exitnach der Verarbeitung der ersten Zeile der Eingabe. Ihr mittlerer Block muss dort ausgelöst werden fürjedenZeile. Anschließend ENDkönnen Sie in einem Block die gefundenen Werte ausdrucken. Dies tun Sie in einem weiteren Codeausschnitt:

awk '{if ($1 > max) max=$1}END{print max}'

Ein weiteres Problem ist, dass Sie mit einer magischen Zahl initialisieren min(9 im ersten Code, den ich zitiert habe, und 0 im zweiten Teil; Variablen, die nicht explizit initialisiert werden, haben den Wert 0, wenn Sie sie in Berechnungen verwenden). Wenn diese magische Zahl nicht in den Zahlenbereich der tatsächlichen Daten fällt, sind die berechneten Mindest- und/oder Höchstwerte falsch. Es ist besser, sowohl Mindest- als auch Höchstwerte auf einen in den Daten gefundenen Wert zu initialisieren.

VerfolgenbeideUm die Min- und Max-Werte zu ändern, benötigen Sie zwei Variablen und beide müssen zeilenweise mit den Daten in der Datei verglichen werden, um festzustellen, ob sie aktualisiert werden müssen.

Da awkArrays unterstützt werden, wäre es naheliegend, Arrays für minund zu verwenden max, mit einem Array-Element pro Spalte. Genau das habe ich im folgenden Code getan.


Verallgemeinert auf eine beliebige Anzahl von Spalten:

NF == 0 {
        # Skip any line that does not have data
        next
}

!initialized {
        # Initialize the max and min for each column from the
        # data on the first line of input that has data.
        # Then immediately skip to next line.

        nf = NF

        for (i = 1; i <= nf; ++i)
                max[i] = min[i] = $i

        initialized = 1
        next
}

{
        # Loop over the columns to see if the max and/or min
        # values need updating.

        for (i = 1; i <= nf; ++i) {
                if (max[i] < $i) max[i] = $i
                if (min[i] > $i) min[i] = $i
        }
}

END {
        # Output max and min values for each column.

        for (i = 1; i <= nf; ++i)
                printf("Column %d: min=%s, max=%s\n", i, min[i], max[i])
}

Angesichts dieses Skripts und der Daten in der Frage:

$ awk -f script.awk file
Column 1: min=0.0000, max=0.4916
Column 2: min=-24.1254, max=-23.4334

Die Bedingung NF == 0für den ersten Block (der für alle Zeilen ausgeführt wird) soll sicherstellen, dass wir leere Zeilen überspringen. Der Test bedeutet „wenn es in dieser Zeile null Felder (Spalten) mit Daten gibt“. Die Variable initializedwird von Anfang an Null sein (logischFALSCH), sondern wird auf eins gesetzt (logischWAHR), sobald die erste Zeile mit Daten gelesen wurde.

Die nfVariable wird in der Zeile, von der aus wir die und -Werte NFinitialisieren, auf (die Anzahl der Felder) initialisiert . Dies ist so, dass die Ausgabe im Block auch dann funktioniert, wenn die letzte Zeile null Felder hat.minmaxEND

Antwort2

Eigentlich kann man alle Anweisungen in einem awkProgramm zusammenfassen:

awk 'NR==1{min1=max1=$1;min2=max2=$2}\
     NR>1 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
            if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
     END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat

Dadurch werden die Minimal- und Maximalwerte für beide Spalten mit den jeweiligen Werten der ersten Zeile initialisiert (Regel mit Bedingung NR==1) und anschließend werden die nachfolgenden Zeilen durchsucht, um zu sehen, ob die Werte jeweils größer als das aktuelle Maximum bzw. kleiner als das aktuelle Minimum sind (Regel mit Bedingung NR>1).

Am Ende der Datei (Regel mit Bedingung END) wird das Ergebnis ausgedruckt.

Beachtendass dies voraussetztEs gibt keine Leerzeilen. Wenn es welche gibt, müssen Sie die NR>1Bedingung durch ersetzen NR>1 && NF>0. Wenn es leere Zeilen geben kannvor dem ersten, verwenden

awk '!init && NF>0 {init=1; min1=max1=$1; min2=max2=$2} \
     init==1 && NF>0 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
                      if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
     END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat

Dabei wird mithilfe einer Variablen initgeprüft, ob bereits eine nicht leere Zeile gefunden wurde, und der Inhalt der ersten nicht leeren Zeile wird verwendet, um das aktuelle Maximum/Minimum für beide Spalten voreinzustellen. Nur wenn initgesetzt ist (nach dieser Initialisierung), werden (nicht leere) Zeilen für die Eingabe dieser Statistik berücksichtigt.

Als allgemeine Bemerkung müssen Sie nie cateine Datei erstellen und das Ergebnis dorthin weiterleiten awk.

Antwort3

Verwenden vondatamashUnd printf:

for f in 1 2 ; do  printf 'Column #%s\nmax - %s\nmin - %s\n\n' $f \
                   $(datamash -W max $f min $f < file.dat); done

...oder ohne Schleife:

printf 'Column #%s\nmax - %s\nmin - %s\n\n' \
       $(datamash -W max 1 min 1 max 2 min 2 < file.dat | 
         tr -s '\t' '\n' | paste - - | nl)

Ausgabe von entweder:

Column #1
max - 0.4916
min - 0

Column #2
max - -23.4334
min - -24.1254

Antwort4

Dies für Spalte 1 (es berechnet den Durchschnitt, Maximum und Minimum)

sort -n -k 1 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1}  END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'

dies für Spalte 2

sort -n -k 2 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1}  END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'

verwandte Informationen