import numpy as np
import pandas as pd
import seaborn as sns
Có những trường hợp trong phân tích data chúng ta cần chọn ra những row có giá trị của biến số Y lớn nhất, nhỏ nhất hoặc thứ nth trong những nhóm nhỏ nào đó.
Ví dụ, trong dataset dưới đây về tiền tip. Chúng ta muốn biết trong 2 nhóm người hút thuốc và không hút thuốc, tiền tip nhiều nhất của mỗi nhóm là bao nhiêu.
tips = sns.load_dataset('tips')
tips.head()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
Tìm mean của total_bill và tip trong các nhóm, phân nhóm
tips.groupby(['time','sex']).mean()
total_bill | tip | size | ||
---|---|---|---|---|
time | sex | |||
Lunch | Male | 18.048485 | 2.882121 | 2.363636 |
Female | 16.339143 | 2.582857 | 2.457143 | |
Dinner | Male | 21.461452 | 3.144839 | 2.701613 |
Female | 19.213077 | 3.002115 | 2.461538 |
Tìm mean, max của 2 biến số khác nhau theo phân nhóm
grp = tips[['total_bill','tip']].groupby([tips['time'],tips['sex']])
grp.agg({'total_bill' : 'mean', 'tip' : 'max'}).round(2)
total_bill | tip | ||
---|---|---|---|
time | sex | ||
Lunch | Male | 18.05 | 6.70 |
Female | 16.34 | 5.17 | |
Dinner | Male | 21.46 | 10.00 |
Female | 19.21 | 6.50 |
Biến số phần trăm tip trong bill được tạo ra và muốn biết top 3 trường hợp có phần trăm tip cao nhất trong dataset
tips['tip_pct'] = tips['tip']/tips['total_bill']
tips.head()
total_bill | tip | sex | smoker | day | time | size | tip_pct | |
---|---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 | 0.059447 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 | 0.160542 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 | 0.166587 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 | 0.139780 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 | 0.146808 |
Top 3 row có tip_pct cao nhất trong dataset nói chung
def top(df, n = 3, column = 'tip_pct'):
return df.sort_values(by = column)[-n:]
top(tips, n = 3)
total_bill | tip | sex | smoker | day | time | size | tip_pct | |
---|---|---|---|---|---|---|---|---|
67 | 3.07 | 1.00 | Female | Yes | Sat | Dinner | 1 | 0.325733 |
178 | 9.60 | 4.00 | Female | Yes | Sun | Dinner | 2 | 0.416667 |
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 |
Sử dụng function apply() cho các nhóm
tips.groupby('smoker').apply(top)
total_bill | tip | sex | smoker | day | time | size | tip_pct | ||
---|---|---|---|---|---|---|---|---|---|
smoker | |||||||||
Yes | 67 | 3.07 | 1.00 | Female | Yes | Sat | Dinner | 1 | 0.325733 |
178 | 9.60 | 4.00 | Female | Yes | Sun | Dinner | 2 | 0.416667 | |
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 | |
No | 51 | 10.29 | 2.60 | Female | No | Sun | Dinner | 2 | 0.252672 |
149 | 7.51 | 2.00 | Male | No | Thur | Lunch | 2 | 0.266312 | |
232 | 11.61 | 3.39 | Male | No | Sat | Dinner | 2 | 0.291990 |
Để dễ theo dõi, hình dung trực quan, ta tạo ra biến số về ranking trong dataset, trong đó ranking giá trị của phần trăm tip (tip_pct) trong các nhóm. Trong đó row có giá trị tip_pct thấp nhất được rank là 1, row có giá trị cao nhất sẽ có rank cao nhất theo nhóm.
tips['rank'] = tips.groupby('smoker')['tip_pct'].rank()
tips.head()
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | |
---|---|---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 | 0.059447 | 2.0 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 | 0.160542 | 85.0 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 | 0.166587 | 95.0 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 | 0.139780 | 45.0 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 | 0.146808 | 60.0 |
Tìm ra các rows thuộc top 3 tip_pct trong các nhóm ‘smoker’
tips.groupby('smoker').apply(top)
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | ||
---|---|---|---|---|---|---|---|---|---|---|
smoker | ||||||||||
Yes | 67 | 3.07 | 1.00 | Female | Yes | Sat | Dinner | 1 | 0.325733 | 91.0 |
178 | 9.60 | 4.00 | Female | Yes | Sun | Dinner | 2 | 0.416667 | 92.0 | |
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 | 93.0 | |
No | 51 | 10.29 | 2.60 | Female | No | Sun | Dinner | 2 | 0.252672 | 149.0 |
149 | 7.51 | 2.00 | Male | No | Thur | Lunch | 2 | 0.266312 | 150.0 | |
232 | 11.61 | 3.39 | Male | No | Sat | Dinner | 2 | 0.291990 | 151.0 |
Để tìm ra những row rank cao nhất trong mỗi nhóm:
tips.groupby(['smoker'], sort=False)['rank'].max()
smoker
No 151.0
Yes 93.0
Name: rank, dtype: float64
tips.loc[(tips['rank'] == 151) | ((tips['rank'] == 93) & (tips['smoker'] == 'Yes'))]
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | |
---|---|---|---|---|---|---|---|---|---|
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 | 93.0 |
232 | 11.61 | 3.39 | Male | No | Sat | Dinner | 2 | 0.291990 | 151.0 |
Một các khác ta ranking theo chiều ngược lại, row có giá trị cao nhất được rank là 1
tips['rank'] = tips.groupby('smoker')['tip_pct'].rank(ascending = False)
tips.groupby('smoker').apply(top)
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | ||
---|---|---|---|---|---|---|---|---|---|---|
smoker | ||||||||||
Yes | 67 | 3.07 | 1.00 | Female | Yes | Sat | Dinner | 1 | 0.325733 | 3.0 |
178 | 9.60 | 4.00 | Female | Yes | Sun | Dinner | 2 | 0.416667 | 2.0 | |
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 | 1.0 | |
No | 51 | 10.29 | 2.60 | Female | No | Sun | Dinner | 2 | 0.252672 | 3.0 |
149 | 7.51 | 2.00 | Male | No | Thur | Lunch | 2 | 0.266312 | 2.0 | |
232 | 11.61 | 3.39 | Male | No | Sat | Dinner | 2 | 0.291990 | 1.0 |
Tìm ra row có tip_pct cao nhất
tips.loc[(tips['rank'] == 1)]
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | |
---|---|---|---|---|---|---|---|---|---|
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 | 1.0 |
232 | 11.61 | 3.39 | Male | No | Sat | Dinner | 2 | 0.291990 | 1.0 |
Đến đây ta có thể tìm ra row có ranking thứ n bất kì, ví dụ n = 10 trong mỗi nhóm
tips.loc[(tips['rank'] == 10)]
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | |
---|---|---|---|---|---|---|---|---|---|
42 | 13.94 | 3.06 | Male | No | Sun | Dinner | 2 | 0.219512 | 10.0 |
174 | 16.82 | 4.00 | Male | Yes | Sun | Dinner | 2 | 0.237812 | 10.0 |
những row có ranking thuộc top 5
tips.loc[(tips['rank'] <= 5)]
total_bill | tip | sex | smoker | day | time | size | tip_pct | rank | |
---|---|---|---|---|---|---|---|---|---|
51 | 10.29 | 2.60 | Female | No | Sun | Dinner | 2 | 0.252672 | 3.0 |
67 | 3.07 | 1.00 | Female | Yes | Sat | Dinner | 1 | 0.325733 | 3.0 |
88 | 24.71 | 5.85 | Male | No | Thur | Lunch | 2 | 0.236746 | 5.0 |
109 | 14.31 | 4.00 | Female | Yes | Sat | Dinner | 2 | 0.279525 | 5.0 |
149 | 7.51 | 2.00 | Male | No | Thur | Lunch | 2 | 0.266312 | 2.0 |
172 | 7.25 | 5.15 | Male | Yes | Sun | Dinner | 2 | 0.710345 | 1.0 |
178 | 9.60 | 4.00 | Female | Yes | Sun | Dinner | 2 | 0.416667 | 2.0 |
183 | 23.17 | 6.50 | Male | Yes | Sun | Dinner | 4 | 0.280535 | 4.0 |
185 | 20.69 | 5.00 | Male | No | Sun | Dinner | 5 | 0.241663 | 4.0 |
232 | 11.61 | 3.39 | Male | No | Sat | Dinner | 2 | 0.291990 | 1.0 |
Đến đây chúng ta có thể lấy data của những row thuộc top 5 về phần trăm tip cao nhất để phân tích.