Как да групирате по сума и средна колона в python?

Като вход имам CSV файл с времена и куп числа за всяко време.

Time,F1,F2,F3
8:11,5,2,4
9:25,9,8,2
9:39,7,3,2
9:53,6,5,1
10:07,4,6,7
10:21,7,3,1
10:35,5,6,7
11:49,1,2,1
12:03,3,3,1

Бих искал да изведа таблицата за всеки час, групирана по колона Средно и Сума:

Time,SUM F1,SUM F2,SUM F3,AVG F1,AVG F2,AVG F3
8:00,5,2,4,5,2,4
9:00,22,16,5,7.3,5.3,1.6
10:00,16,15,15,5.3,5,5
11:00,1,2,1,1,2,1
12:00,3,3,1,3,3,1

Досега гледах да го направя с речник, където часът е ключ, а стойността е списък от брой и сума, след което разделих сумата на брой, за да получа средна стойност. Сигурен съм, че трябва да има по-чист начин да го направим. Може би някоя библиотека може да работи с това. Някакви предположения?


person user52028778    schedule 22.01.2016    source източник
comment
Подходът ти е добър. Това също не е толкова много код. Цикъл за добавяне на неща към три речника, като всеки използва setdefault(hour, []).append(F1) и setdefault(hour, []).append(F2) и setdefault(hour, []).append(F3). След това за всеки dict итерирате през всеки час и извиквате 'sum' над списъка и разделяте на count(list), като внимавате да се справите с това, което се случва, когато списъкът ви е празен.   -  person Peter pete    schedule 22.01.2016
comment
Pandas е добра библиотека за този вид обработка на данни: pandas.pydata.org   -  person CoMartel    schedule 22.01.2016


Отговори (2)


Решение за pandas:

import pandas as pd

df = pd.read_csv('f123.csv')
df['Time'] = df['Time'].apply(lambda x: x.split(':')[0] + ':00')
by_hour = df.groupby('Time')
data = {}
for name in ['F1', 'F2', 'F3']:
    data['SUM ' + name] = by_hour[name].sum()
    data['AVG ' + name] = by_hour[name].mean()
res = pd.DataFrame(data)
print(res)

отпечатъци:

         AVG F1    AVG F2    AVG F3  SUM F1  SUM F2  SUM F3
Time                                                       
10:00  5.333333  5.000000  5.000000      16      15      15
11:00  1.000000  2.000000  1.000000       1       2       1
12:00  3.000000  3.000000  1.000000       3       3       1
8:00   5.000000  2.000000  4.000000       5       2       4
9:00   7.333333  5.333333  1.666667      22      16       5

Запазете като csv файл:

res.to_csv('res.csv')

Това е съдържанието на res.csv:

Time,AVG F1,AVG F2,AVG F3,SUM F1,SUM F2,SUM F3
10:00,5.333333333333333,5.0,5.0,16,15,15
11:00,1.0,2.0,1.0,1,2,1
12:00,3.0,3.0,1.0,3,3,1
8:00,5.0,2.0,4.0,5,2,4
9:00,7.333333333333333,5.333333333333333,1.6666666666666667,22,16,5
person Mike Müller    schedule 22.01.2016
comment
Чудесно решение! Как бихте се справили с новите дни, дадена колона с дати до часа във формат „22-01-16“? - person user52028778; 22.01.2016
comment
Страхотно, че помогна. Pandas много добре чете и работи с дати като цяло. Отговорът на нов въпрос в коментар обаче е наистина тромав. Би било по-лесно да зададете нов въпрос и да го свържете в коментар от тук. Ще го разгледам. - person Mike Müller; 22.01.2016
comment
Pands изглежда страхотно наистина, но манипулирането на данни там не е много интуитивно на пръв поглед, може би трябва да посещавам някой от класовете на Python-academy. Тук добавих нов въпрос: stackoverflow.com/questions/34944183/ - person user52028778; 22.01.2016

Следното трябва да ви помогне да започнете, то използва модула csv на Python за обработете файловете и itertools.groupby за групиране на записите по часове:

import csv
from itertools import groupby, chain

with open('input.csv', 'rb') as f_input, open('output.csv', 'wb') as f_output:
    csv_input = csv.reader(f_input)
    csv_output = csv.writer(f_output)
    header = next(csv_input)
    csv_output.writerow(["Time","SUM F1","SUM F2","SUM F3","AVG F1","AVG F2","AVG F3"])

    for k, g in groupby(csv_input, lambda x: int(x[0].split(':')[0])):
        entries = [(int(f1), int(f2), int(f3)) for t, f1, f2, f3 in g]
        sums = [(sum(x), sum(x)/float(len(entries))) for x in zip(*entries)]
        row = ['{}:00'.format(k)] + list(chain.from_iterable(zip(*sums)))
        csv_output.writerow(row)

Това ще ви даде изходен csv файл, изглеждащ така:

 Time,SUM F1,SUM F2,SUM F3,AVG F1,AVG F2,AVG F3
 8:00,5,2,4,5.0,2.0,4.0
 9:00,22,16,5,7.333333333333333,5.333333333333333,1.6666666666666667
 10:00,16,15,15,5.333333333333333,5.0,5.0
 11:00,1,2,1,1.0,2.0,1.0
 12:00,3,3,1,3.0,3.0,1.0

zip се използва за транспониране на записите в колоните.

Тествано с помощта на Python 2.7.9

person Martin Evans    schedule 22.01.2016