2012-11-07 22 views
7

Ho 500 file con nome fort.1, fort.2 ... fort.500. Ogni file contiene 800 dati come qui sotto:calcolare media usando awk da più file

1 0,485
2 0,028
3 0,100
4 0,979
5 0,338
6 0,891
7 0,415
8 0,368
9 0,245
10 0.489

Voglio ottenere la media di ogni riga della seconda colonna da ogni file. In altre parole, ottieni la media della seconda colonna della prima riga da tutti i file e archivia in "output.file". Quindi ottieni la media della seconda colonna della seconda riga e memorizza nello stesso "file di output". Ho provato con il comando incolla ma non riesco ad ottenere ciò che voglio. C'è un modo per farlo in AWK?

Apprezzare qualsiasi aiuto. Grazie

risposta

1

La mia comprensione: ogni file è un insieme di misurazioni in una determinata posizione. Si desidera aggregare le misurazioni in tutte le posizioni, facendo una media del valore della stessa riga in ogni file in un nuovo file.

Supponendo che la prima colonna può essere trattata come un ID per la fila (e ci sono 800 misurazioni in un file):

cat fort.* | awk ' 
BEGIN { 
    for (i = 1; i <= 800; i++) 
     total[i] = 0 
} 

{ total[$1] += $2 } 

END { 
    for (i = 1; i <= 800; i++) 
     print i, total[i]/500 
} 
' 

In primo luogo, inizializzare un array per memorizzare la somma per una riga in tutti File.

Quindi, passiamo in rassegna i file concatenati. Usiamo la prima colonna come chiave per la riga e sommiamo nell'array.

Infine, eseguiamo il loop sull'array e stampiamo il valore medio per riga su tutti i file.

+0

In questo codice quello che ho capito è che in un primo momento tutti i valori il file fort.1 rimane nell'array "totale". Poi va a leggere il secondo file fort.2 e mantenere il totale dell'array. (Ad esempio), quindi deve eseguire (totale [1] + totale [1]/2) rispettivamente dal primo e dal secondo file, per ottenere la media. Ma non capisco ... Scusa se ho capito male. – Vijay

+0

Modificato per riflettere le mie supposizioni sul problema. –

+0

Grazie per la risposta veloce. Permettetemi di chiarire di nuovo ciò che voglio. Ogni file (totale di 500 file) contiene due colonne (1a colonna e 2a colonna) e 800 righe di righe.Voglio la prima riga, la seconda colonna di ogni file (tutti i 500 file) da aggiungere e calcolare la media e memorizzare in un nuovo file come average.output. Quindi passa alla seconda riga, 2a colonna di tutti i file (500 file) e calcola la media e memorizza in media.output. E continua fino a quando il file average.output contiene 800 righe. Vorrei avere questa spiegazione. Scusa se la mia domanda nel post ti ha confuso. Grazie in anticipo. – Vijay

2

Supponendo che la prima colonna è un ID:

cat fort.* | awk '{sum[$1] += $2; counts[$1]++;} END {for (i in sum) print i, sum[i]/counts[i];}' 
5

Ecco un modo veloce utilizzando paste e awk:

paste fort.* | awk '{ for(i=2;i<=NF;i+=2) array[$1]+=$i; if (i = NF) print $1, array[$1]/NF*2 }' > output.file 

Come alcune delle altre risposte; Ecco un altro modo, ma questo usa sort per ottenere l'output numerico ordinato:

awk '{ sum[$1]+=$2; cnt[$1]++ } END { for (i in sum) print i, sum[i]/cnt[i] | "sort -n" }' fort.* 
7

awk senza alcuna assunzione al 1 ° colonna:

awk '{a[FNR]+=$2;b[FNR]++;}END{for(i=1;i<=FNR;i++)print i,a[i]/b[i];}' fort.* 
+0

Questo codice considera tutto "prima riga di tutti i file di input (fort.1, fort.2 ...)" e calcola la media e successivamente passa alla seconda riga di tutti i file (fort.1, fort.2 ... .) fino a 800 righe da ciascun file? Ho bisogno di spiegazioni per capire cosa fa effettivamente questo codice. Grazie – Vijay

+0

@ Vijay: Lo ha effettivamente .. aggiornato con il forte. * Per renderlo più chiaro. Puoi testarlo su un piccolo file di esempio per confermare ... Guru – Guru

+0

, questo codice funziona bene. Grazie. Inoltre, è necessario aggiungere una piccola cosa. Ho file con nomi fort.1, fort.2 e così via. Ho paura che se metto fort *, leggerà fort.1, fort.10, fort.100 invece di fort.1, fort.2 e così via. Come può essere trattato? Grazie – Vijay

Problemi correlati