średnie csv w linii poleceń linux

2

Mam duży plik pełen takich rekordów

1, 2, 4, 5, 6
1, 3, 5, 6, 3
1, 4, 5, 6, 6
2, 4, 5, 5, 5
2, 3, 4, 5, 2

w każdym razie muszę wziąć średnią wszystkich wierszy z tym samym pierwszym numerem (kluczem). to znaczy

1, 3, 4.66, 5.66, 5
2, 3.5, 4.5, 5, 3.5

Wiem, że jest to coś, w czym świetny byłby awk / sed, po prostu nie mam wystarczającego doświadczenia z nimi, aby to osiągnąć, dzięki!

A co powiesz na uśrednianie tych kolumn razem? więc po wysłaniu tego do pliku id chce uzyskać inny, taki jak:

1, 4.58
1, 4.125

Liczba kolumn do dodania może nie zawsze wynosić 4.

EDYCJA: może to być łatwiejsze do zrobienia w gnuplot, więc potrzebuję głównie odpowiedzi na pierwszą część.

Flamewires
źródło
Czy wiersze są posortowane (pole zgrupowane), jak pokazano w przykładzie? Mówisz, że liczba pól w rekordzie może być inna. Czy są spójne w pliku?
Dennis Williamson,
cóż, to tylko sort -n, aby je posortować, więc nie ma problemu. Tak. i tak, są spójne w pliku, ale nie między plikami. Jeśli masz odpowiedź, która zależy ode mnie, określając liczbę pól, to dobrze, ja też to wezmę. Po prostu próbuję
napisać

Odpowiedzi:

2

W przypadku pierwszej opcji:

awk -F, 'BEGIN { OFS=","} {if (!keys[$1]) {keys[$1] = 1}; for (i=2;i<=NF;i++){array[$1,i]+=$i}; count[$1]+=1}END{for (i in keys) {printf ("%s ", i); for (j=2;j<=NF;j++) {printf ("%.2f ", array[i,j]/count[i])}; printf ("%s","\n")}}' inputfile

W przypadku drugiej opcji:

awk -F, 'BEGIN { OFS=","} {if (!keys[$1]) {keys[$1] = 1}; for (i=2;i<=NF;i++){array[$1,i]+=$i}; count[$1]+=1}END{for (i in keys) {{printf ("%s ", i); sum = 0; for (j=2;j<=NF;j++) {sum += array[i,j]/count[i]}}; printf ("%.2f\n",sum/(NF-1))}}' inputfile

ale nie jestem pewien, czy rozumiem, dlaczego chcesz mieć średnią z niektórych średnich.

Dennis Williamson
źródło
0

Jest to zaskakująco trudne i skomplikowane przy użyciu Sed, więc oto hack Pythona, aby to zrobić:

#!/usr/bin/env python

f = open("mycsv","r")
values = {}
index = {}
for line in f:
    rownum = line.strip().split(", ")
    try:
        values[rownum[0]] = map(lambda x,y: x+y, values[rownum[0]], [float(x) for x in rownum[1:]])
        index[rownum[0]] += 1
    except KeyError:
        values[rownum[0]] = [ float(x) for x in rownum[1:] ]
        index[rownum[0]] = 1

for k,v in values.items():
    values[k] = [x/index[k] for x in values[k]]
    print k, ":", values[k]

Działa to niezależnie od kolejności rzędów, o ile rzędy z tym samym pierwszym elementem mają tę samą długość.

Uśrednianie razem kolumn zajmie jeszcze jedną linię Pythona w pętli for:

print reduce(lambda x,y: x+y, values[k])/len(values[k])

Biorąc jednak pod uwagę ogromną liczbę list, prawdopodobnie lepiej jest rozwiązać ten problem za pomocą NumPy lub Matlab.

Karthik
źródło
0

Karthik ma dobrą sugestię, aby zrobić to w Numpy: to tylko kilka linijek,

import numpy
data = numpy.loadtxt('filename.txt')
for key in numpy.unique(data.T[0]):
    print data[data.T[0]==key].mean(0)

Lub jeśli chcesz uśrednić kolumny razem, ostatni wiersz zmieni się na

    avgs = data[data.T[0]==key].mean(0)[1:]
    print avgs[0], avgs[1:].mean()
David Z
źródło