2015-10-22 14 views
5

Mam plik CSV, który zawiera 3 kolumny, count_id, AMV i godzinę.Ramka danych Pand - rachunek lambda i minimalna wartość na serię

Używam pand i przeczytałem to jako ramkę danych.

results= pd.read_csv('./output.csv') 

Najpierw najpierw sortuję ramkę danych dla count_id, a następnie dla AMV.

results_sorted = results.sort_index(by=['count_id','AMV'], ascending=[True, True]) 

Daje

count_id AMV Hour 
0 16012E 4004 14 
1 16012E 4026 12 
2 16012E 4099 15 
3 16012E 4167 11 
4 16012E 4239 10 
5 16012E 4324 13 
6 16012E 4941 16 
7 16012E 5088 17 
8 16012E 5283  9 
9 16012E 5620  8 
10 16012E 5946 18 
11 16012E 6146  7 
12 16012W 3622 10 
13 16012W 3904 12 
14 16012W 3979 11 
15 16012W 4076  9 
16 16012W 4189 13 
17 16012W 4870 14 
18 16012W 4899 18 
19 16012W 5107 15 
20 16012W 5659  8 
21 16012W 6325  7 
22 16012W 6460 17 
23 16012W 6500 16 

teraz chcę wykonać jakąś normalizację na danych, aby można było ostatecznie wykreślić ją na tej samej działce. Chciałbym znaleźć minimalną wartość AMV dla serii (count_id), a następnie odjąć tę minimalną wartość od podanej wartości AMV. To da mi nową kolumnę AMV_norm.

Która będzie wyglądać:

count_id AMV Hour AMV_norm 
0 16012E 4004 14   0 
1 16012E 4026 12  22 
2 16012E 4099 15  95 
3 16012E 4167 11  163 
4 16012E 4239 10  235 
5 16012E 4324 13  320 
6 16012E 4941 16  937 
7 16012E 5088 17  1084 
8 16012E 5283  9  1279 
9 16012E 5620  8  1616 
10 16012E 5946 18  1942 
11 16012E 6146  7  2142 
12 16012W 3622 10   0 
13 16012W 3904 12  282 
14 16012W 3979 11  357 
15 16012W 4076  9  454 
16 16012W 4189 13  567 
17 16012W 4870 14  1248 
18 16012W 4899 18  1277 
19 16012W 5107 15  1485 
20 16012W 5659  8  2037 
21 16012W 6325  7  2703 
22 16012W 6460 17  2838 
23 16012W 6500 16  2878 

Jak mogę zdefiniować funkcję, która wyznaczy minimalną wartość AMV za serii, a nie minimalna wartość AMV ogólnej? Wyglądałoby to mniej więcej tak:

def minimum_series_value(AMV): 
    return AMV.argmin() 

Następnie musiałbym utworzyć nową kolumnę i za pomocą funkcji lambda zapełnić ten wiersz. Wiem, że to wyglądać mniej więcej tak:

results_sorted['AMV_norm'] = results_sorted.apply(lambda row:results_sorted(row['AMV'])) 

Odpowiedz

3

odjąć od kolumny AMV min Transformacja:

In [11]: df.groupby('count_id')["AMV"].transform('min') 
Out[11]: 
0  4004 
1  4004 
2  4004 
3  4004 
4  4004 
... 
21 3622 
22 3622 
23 3622 
dtype: int64 

In [12]: df["AMV"] - df.groupby('count_id')["AMV"].transform('min') 
Out[12]: 
0  0 
1  22 
2  95 
3  163 
4  235 
... 
21 2703 
22 2838 
23 2878 
dtype: int64 

In [13]: df["AMV_norm"] = df["AMV"] - df.groupby('count_id')["AMV"].transform('min') 
+0

Dziękuję;) Bardzo jasne i proste – LearningSlowly

1

wierzę chcesz grupy na count_id, a następnie obliczyć różnicę między bieżących wartości i wartości minimalnej dla tej grupy.

df['AMV_norm'] = (df.groupby('count_id').AMV 
        .transform(lambda group_series: group_series - np.min(group_series))) 

>>> df 
    count_id AMV Hour AMV_norm 
0 16012E 4004 14   0 
1 16012E 4026 12  22 
2 16012E 4099 15  95 
3 16012E 4167 11  163 
4 16012E 4239 10  235 
5 16012E 4324 13  320 
6 16012E 4941 16  937 
7 16012E 5088 17  1084 
8 16012E 5283  9  1279 
9 16012E 5620  8  1616 
10 16012E 5946 18  1942 
11 16012E 6146  7  2142 
12 16012W 3622 10   0 
13 16012W 3904 12  282 
14 16012W 3979 11  357 
15 16012W 4076  9  454 
16 16012W 4189 13  567 
17 16012W 4870 14  1248 
18 16012W 4899 18  1277 
19 16012W 5107 15  1485 
20 16012W 5659  8  2037 
21 16012W 6325  7  2703 
22 16012W 6460 17  2838 
23 16012W 6500 16  2878 

EDIT: Podejście przez @AndyHayden nieco szybciej:

%timeit df["AMV"] - df.groupby('count_id')["AMV"].transform('min') 
1000 loops, best of 3: 736 µs per loop 

%timeit df.groupby('count_id').AMV.transform(lambda x: x - np.min(x)) 
1000 loops, best of 3: 804 µs per loop 

%timeit df.groupby('count_id').AMV.apply(lambda x: x - np.min(x)) 
1000 loops, best of 3: 1.32 ms per loop 
+1

to dziwne, użycie lambda która zwraca Serię w transformacji! (Zamiast używać apliakcji.) –

+0

Sądzę, że używają tej samej ścieżki, * ale * transformacja zwykle oznacza, że ​​jedna wartość jest rozłożona na grupę (na przykład transformacja ("min")), podczas gdy zastosowanie oznacza, że ​​grupa może zwrócić wszystko. Ale wiesz, nie jestem pewien, to było moje zrozumienie. –

+0

Interesujące, dziękuję. Bardziej komfortowo używam lambda, ale jak mówisz odpowiedź Andy'ego jest szybsza. Dzięki za wysiłek! – LearningSlowly

Powiązane problemy