csv calcula a média na linha de comando do linux

2

Eu tenho um arquivo grande cheio de registros como este

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

de qualquer forma, eu preciso pegar a média de todas as linhas com o mesmo primeiro número (chave). ou seja,

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

Eu sei que isso é algo que o awk / sed seria ótimo, eu simplesmente não tenho experiência suficiente com eles para realizá-lo, obrigado!

Além disso, e a média dessas colunas juntas? então, depois de eu gerar isso para um arquivo, id gostaria de pegar outro como:

1, 4.58
1, 4.125

O número de colunas para adicionar nem sempre pode ser 4.

EDIT: isso pode ser mais fácil de fazer no gnuplot, então eu só preciso de uma resposta para a primeira parte.

    
por Flamewires 20.07.2010 / 20:55

3 respostas

2

Para a primeira opção:

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

Para a segunda opção:

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

mas não tenho certeza se entendi por que você deseja a média de algumas médias.

    
por 21.07.2010 / 00:18
0

Isso é surpreendentemente complicado e complicado usando o Sed, então aqui está um hack do Python para fazer isso:

#!/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]

Isso funciona independentemente da ordem das linhas, desde que as linhas com o mesmo primeiro elemento tenham o mesmo tamanho.

A média das colunas juntas levará apenas mais uma linha do Python no loop for:

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

Dado o número angustiante de compreensões de lista, você provavelmente está melhor enfrentando esse problema com o NumPy ou o Matlab.

    
por 20.07.2010 / 23:30
0

Karthik tem uma boa sugestão para fazer isso em Numpy: são apenas algumas linhas,

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

Ou se você quisesse calcular a média das colunas juntas, a última linha mudaria para

    avgs = data[data.T[0]==key].mean(0)[1:]
    print avgs[0], avgs[1:].mean()
    
por 21.07.2010 / 02:22

Tags