Python панды: сохранить строку с наибольшим значением столбца - PullRequest
0 голосов
/ 11 мая 2018

Скажем, у меня есть данные тестовых баллов студентов, где каждый студент изучает разные предметы. Каждый студент может пройти тест по каждому предмету несколько раз, и будет сохранен только самый высокий балл (из 100). Например, скажем, у меня есть данные всех тестовых записей:

| student_name | subject | test_number | score | 
|--------------|---------|-------------|-------|
| sarah        | maths   | test1       | 78    |
| sarah        | maths   | test2       | 71    |
| sarah        | maths   | test3       | 83    |
| sarah        | physics | test1       | 91    |
| sarah        | physics | test2       | 97    |
| sarah        | history | test1       | 83    |
| sarah        | history | test2       | 87    |
| joan         | maths   | test1       | 83    |
| joan         | maths   | test2       | 88    |

(1) Как сохранить только записи теста (строки) с максимальной оценкой? То есть

| student_name | subject | test_number | score | 
|--------------|---------|-------------|-------|
| sarah        | maths   | test1       | 78    |
| sarah        | maths   | test2       | 71    |
| sarah        | maths   | test3       | 83    |
| sarah        | physics | test1       | 91    |

(2) Как бы я сохранил среднее всех тестов по одному и тому же предмету для одного и того же студента? То есть:

| student_name | subject | test_number | ave_score | 
|--------------|---------|-------------|-----------|
| sarah        | maths   | na          | 77.333    |
| sarah        | maths   | na          | 94        |
| sarah        | maths   | na          | 85        |
| sarah        | physics | na          | 85.5      |

Я пробовал различные комбинации df.sort_values() и df.drop_duplicates(subset=..., keep=...), но безрезультатно.

Фактические данные

| query | target   | pct-similarity | p-val | aln_length | bit-score |
|-------|----------|----------------|-------|------------|-----------|
| EV239 | B/Fw6/623 | 99.23         | 0.966 |  832       | 356       |
| EV239 | B/Fw6/623 | 97.34         | 0.982 |  1022      | 739       |
| EV239 | MMS-alpha | 92.23         | 0.997 |  838       | 384       |
| EV239 | MMS-alpha | 93.49         | 0.993 |  1402      | 829       |
| EV380 | B/Fw6/623 | 94.32         | 0.951 |  324       | 423       |
| EV380 | B/Fw6/623 | 95.27         | 0.932 |  1245      | 938       |
| EV380 | MMS-alpha | 99.23         | 0.927 |  723       | 522       |
| EV380 | MMS-alpha | 99.15         | 0.903 |  948       | 1092      |

После применения функции агрегирования будет интересен только столбец pct-similarity.

(1) Удалить дубликаты запроса + целевые строки, выбрав максимальное значение aln_length. Сохраните значение pct-similarity, принадлежащее строке, с максимальным значением aln_length.

(2) Агрегируйте повторяющиеся строки запроса + назначения, выбирая строку с максимальным значением aln_length и вычисляя среднее значение pct-similarity для этого набора повторяющихся строк. Другие числовые столбцы не нужны и будут в конечном итоге отброшены, поэтому мне действительно все равно, какая функция агрегации (максимальная или средняя) применяется к ним.

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Скорее всего describe может

df.groupby(["student_name","subject"]).score.describe()
Out[15]: 
                          count       mean       std   min    25%   50%  \
student_name   subject                                                    
 joan           maths       2.0  85.500000  3.535534  83.0  84.25  85.5   
 sarah          history     2.0  85.000000  2.828427  83.0  84.00  85.0   
                maths       3.0  77.333333  6.027714  71.0  74.50  78.0   
                physics     2.0  94.000000  4.242641  91.0  92.50  94.0   
                            75%   max  
student_name   subject                 
 joan           maths     86.75  88.0  
 sarah          history   86.00  87.0  
                maths     80.50  83.0  
                physics   95.50  97.0  

И с drop_duplicates

df.sort_values('score').drop_duplicates(["student_name","subject"],keep='last')
Out[22]: 
     student_name    subject    test_number  score
2   sarah           maths      test3            83
6   sarah           history    test2            87
8   joan            maths      test2            88
4   sarah           physics    test2            97

Для mean значение с reindex

df.groupby(["student_name","subject"], as_index=False).mean().reindex(columns=df.columns)
Out[24]: 
     student_name    subject  test_number      score
0   joan            maths             NaN  85.500000
1   sarah           history           NaN  85.000000
2   sarah           maths             NaN  77.333333
3   sarah           physics           NaN  94.000000
0 голосов
/ 11 мая 2018

Мы можем использовать agg на groupby, чтобы получить 'idxmax' и 'mean'.
. Таким образом, мы можем выполнить внутреннее соединение, чтобы получить как правильные строки, так и средние значения.

df.join(
    df.groupby(['student_name', 'subject'])
      .score.agg(['idxmax', 'mean']).set_index('idxmax'),
    how='inner'
)

  student_name  subject test_number  score       mean
2        sarah    maths       test3     83  77.333333
4        sarah  physics       test2     97  94.000000
6        sarah  history       test2     87  85.000000
8         joan    maths       test2     88  85.500000
0 голосов
/ 11 мая 2018

Просто используйте max() для каждой группы учащихся / предмета:

df.groupby(["student_name","subject"], as_index=False).max()


    student_name    subject         test_number     score
0   joan            maths           test2           88
1   sarah           history         test2           87
2   sarah           maths           test3           83
3   sarah           physics         test2           97

Для среднего значения используйте mean() вместо:

df.groupby(["student_name","subject"], as_index=False).mean()

    student_name    subject     score
0   joan            maths       85.500000
1   sarah           history     85.000000
2   sarah           maths       77.333333
3   sarah           physics     94.000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...