Панды находят определенную строку из индекса строки и возвращают значение в новый столбец

avatar
Kelvin Lo
9 августа 2021 в 05:51
62
1
0

Я создаю новый столбец на основе данных о том, проводил ли учащийся повторный тест по предмету на основе столбца "файл":

Это данные строки:

enter image description here

Вот как я хочу добиться:

enter image description here

Это мой код:

import pandas as pd
df = pd.DataFrame(columns=['file', 'class', 'student', 'subject', 'scores'],
              data=[['re_test', 'A', 'John', 'Math', 60], 
                    ['first_test', 'A', 'Scott', 'Math', 75], 
                    ['first_test', 'A', 'Mary', 'Math', 80],
                    ['re_test', 'B', 'Jack', 'Math', 70], 
                    ['first_test', 'B', 'Mina', 'Math', 75],
                    ['first_test', 'B', 'James', 'Math', 95]])
 
df_math= df.pivot_table(index= ['class', 'student', 'file'],
           values=['subject'], aggfunc=['count'], fill_value = 0)

def retest_check(res):
    res_check = []

    if 're' in res['file']:
        res_check.append(f'Yes')
    else:
        res_check.append(f'No')

    return res_check

df_math['Re-test'] = df_math.apply(retest_check, axis=1)

Мой код выдает ошибку, которая, похоже, не может идентифицировать строку в столбце "файл". Как я могу решить эту проблему? Спасибо.

KeyError: 'файл'

Источник

Ответы (1)

avatar
mozway
9 августа 2021 в 05:59
1

Вы можете использовать этот подход:

(df.query('subject == "Math"')
   .groupby(['class', 'student'])
   .agg({'subject': 'count',
         'file': lambda s: 'Yes' if 're_test' in s.values else 'No',
        })
   .rename(columns={'subject': 'Math (Count)', 'file': 'Re-test'})
)

выход:

               Math (Count) Re-test
class student                      
A     John                1     Yes
      Mary                1      No
      Scott               1      No
B     Jack                1     Yes
      James               1      No
      Mina                1      No
Kelvin Lo
9 августа 2021 в 06:09
0

Большое спасибо Mozway! Это почти то, что я хочу. Еще одно мое требование - искать определенную строку «re» в столбце «файл». Есть ли способ изменить лямбда-функцию? Мой реальный набор данных в столбце «файл» длиннее и сложнее, чем просто строка «повторное тестирование». Например, «University-Class123-Math-re_test-20210804_201414». Я могу идентифицировать только подстроку «re» как индикатор, указывающий на повторное тестирование или нет.

mozway
9 августа 2021 в 06:13
0

Конечно, вы можете заменить 're_test' in s.values на s.str.match('.*re_').sum()>0. (Здесь я тестировал "re_", а не "re", так как у вас меньше шансов получить совпадение с обычным словом (например, University-Oregon будет соответствовать только re)

Kelvin Lo
12 августа 2021 в 02:50
0

Привет mozway, простите за еще один вопрос. Если мне нужно вернуть «Да» с отметкой времени, используя пример «University-Class123-Math-re_test-20210804_201414» в столбце «Повторное тестирование». Как я могу этого добиться? Я пробовал lambda s: 'Yes, {}'.format(s.str.extract(r'(\d{8})'), но, кажется, возвращает каждую строку набора данных.