Linux komut satırında csv ortalamaları


2

Bunun gibi kayıtlarla dolu büyük bir dosyam var

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

Yine de aynı 1. sayıya sahip tüm satırların ortalamasını almam gerekiyor (anahtar). yani

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

Bunun awk / sed için iyi olacağını biliyorum, bunu başarmak için onlarla yeterli deneyime sahip değilim, teşekkürler!

Ayrıca, bu sütunların bir araya getirilmesinden ne haber? bu yüzden, bunu bir dosyaya çıkardıktan sonra, bir tane daha elde etmek istiyorum:

1, 4.58
1, 4.125

Eklenecek sütun sayısı da her zaman 4 olmayabilir.

EDIT: gnuplot'ta bunu yapmak daha kolay olabilir, bu yüzden esas olarak ilk kısım için bir cevaba ihtiyacım var.


Örnekte gösterildiği gibi satırlar sıralandı mı (alan bir gruplandırılmış)? Bir kayıttaki alanların sayısının farklı olabileceğini söylüyorsunuz. Bir dosyada tutarlılar mı?
Dennis Williamson,

iyi, sadece bir sıralama -n onları sıralamak böylece hiçbir sorun. Evet. ve evet onlar dosyada tutarlı, dosyadan dosyaya değil. Alan sayısını belirttiğime bağlı bir cevabınız varsa, sorun değil, bunu da kabul ediyorum. Sadece ayrılmadan önce bu senaryoyu almaya çalışıyorum :)
Flamewires

Yanıtlar:


2

İlk seçenek için:

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

İkinci seçenek için:

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

fakat bazı ortalamaların neden ortalama olmasını istediğinizi anladığımdan emin değilim.


0

Bu Sed kullanarak şaşırtıcı derecede zor ve karmaşık, işte burada bunu yapmak için bir Python kesmek:

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

Bu, aynı birinci elemana sahip satırlar aynı uzunlukta olduğu sürece, satırların sırasına bakılmaksızın çalışır.

Sütunların ortalama alınması, for döngüsünde sadece bir tane daha Python satırı alır:

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

Sıkıntı verici liste kavrama sayısı göz önüne alındığında, bu sorunu NumPy veya Matlab ile çözmekte daha iyi olursunuz.


0

Karthik'in Numpy'de yapması için iyi bir önerisi var: sadece birkaç satır,

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

Veya sütunları birlikte ortalamak istiyorsanız, son satır

    avgs = data[data.T[0]==key].mean(0)[1:]
    print avgs[0], avgs[1:].mean()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.