Как получить доступ к значению серии Pandas в пользовательской функции

#python #pandas #jupyter

#python #pandas #jupyter

Вопрос:

Я работаю над проектом по мониторингу моего времени 5k для моих занятий бегом / бегом трусцой на основе их данных GPS. В настоящее время я изучаю свои данные в записной книжке Jupyter и теперь понимаю, что мне нужно будет исключить некоторые действия.

Каждое действие представляет собой строку в фрейме данных. Хотя я хочу исключить некоторые строки, я не хочу удалять их из своего фрейма данных, поскольку я также буду использовать df для других вычислений.

Я добавил столбец в df вместе с пользовательской функцией для проверки причин недействительности строки. Возможно, что запуск может быть исключен по нескольким причинам.

 In []:
    # add invalidity reasons column amp; update logic
    df['invalidity_reasons'] = ''
    
    def maintain_invalidity_reasons(reason):
        """logic for maintaining ['invalidity reasons']"""
        reasons = []
        if invalidity_reasons == '':
            return list(reason)
        else:
            reasons = invalidity_reasons
            reasons.append(reason)
            return reasons
 

Я фильтрую до определенных строк в моем df и передаю их в свою функцию. Приведенный ниже пример возвращает набор из пяти строк из df. Ниже приведен пример использования функции в моем ноутбуке Jupyter.

 In []:
    columns = ['distance','duration','notes']
    
    filt = (df['duration'] < pd.Timedelta('5 minutes'))
    df.loc[filt,columns].apply(maintain_invalidity_reasons('short_run'),axis=1)

Out []:
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-107-0bd06407ef08> in <module>
          2 
          3 filt = (df['duration'] < pd.Timedelta('5 minutes'))
    ----> 4 df.loc[filt,columns].apply(maintain_invalidity_reasons(reason='short_run'),axis=1)
    
    <ipython-input-106-60264b9c7b13> in maintain_invalidity_reasons(reason)
          5     """logic for maintaining ['invalidity reasons']"""
          6     reasons = []
    ----> 7     if invalidity_reasons == '':
          8         return list(reason)
          9     else:
    
    NameError: name 'invalidity_reasons' is not defined
 

Вот пример вывода моего фильтра, если я удалю вызов .apply() для моей функции

 In []:
columns = ['distance','duration', 'notes','invalidity_reasons']

filt = (df['duration'] < pd.Timedelta('5 minutes'))
df.loc[filt,columns]

Out []:
 

вывод отфильтрованного фрейма данных

Похоже, моя проблема заключается в том, что я не знаю, как указать, что я хочу ссылаться на скалярное значение в индексе / столбце ‘invalidity_reasons’ (не уверен в правильном термине) конкретной строки.

Я попытался настроить IF оператор с помощью приведенных ниже вариантов. Я также пытался применить функцию с / без аргумента axis. Я застрял, пожалуйста, помогите!

 if 'invalidity_reasons' == '':
if s['invalidity_reasons'] == '':
 

Комментарии:

1. Это суп с кодом. invalidity_reasons нигде не определяется до его использования и list(reason) не выполняет то, что вы думаете.

2. Я верю вам в отношении list(reason) проблемы. Как только я определю, как правильно получить доступ к значению в серии (т. Е. К строке), я смогу устранить его в дальнейшем. invalidity_reasons это столбец df, который я создаю перед началом любой фильтрации df. Это упоминается в первой строке первого блока кода в моем сообщении (прямо под комментарием). Для каждой строки начальная часть invalidity_reasons является пустой строкой, пока мне не понадобится обновить ее с помощью моей функции.

3. Кроме того, я немного новичок в Python и Pandas, поэтому я с радостью приму любые отзывы о том, как улучшить мой code soup.

4. Это if 'invalidity_reasons' == '' не имеет смысла (всегда будет False ). И, как указал cs95, у вас нет имени переменной invalidity_reasons . Тот факт, что в вашем фрейме есть столбец с таким именем, этого не делает.

5. invalidity_reasons предполагается, что это не переменная, а скорее индекс / метка скалярного значения в каждой серии (т.Е. Строке), которую я передаю своей функции. Чтобы прояснить свое намерение, я обновил свой пост примером вывода моего фильтра без вызова .apply(), чтобы показать, на какие данные я хочу, чтобы моя функция действовала.

Ответ №1:

Это в значительной степени удар в темноте, но я надеюсь, что это поможет. В следующем я использую этот простой фрейм в качестве примера (чтобы было с чем работать):

 df = pd.DataFrame({'Col': range(5)})
 

Теперь, если вы определяете

 def maintain_invalidity_reasons(current_reasons, new_reason):
    if current_reasons == '':
        return [new_reason]
    if type(current_reasons) == list:
        return current_reasons   [new_reason]
    return [current_reasons]   [new_reason]
 

добавьте еще один столбец invalidity_reasons в df

 df['invalidity_reasons'] = ''
 

заполните одну ячейку (для примера)

 df.loc[0, 'invalidity_reasons'] = 'a reason'
 
    Col invalidity_reasons
0    0           a reason
1    1                   
2    2                   
3    3                   
4    4                   
 

создайте фильтр

 filt = (df.Col < 3)
 

а затем выполните

 df.loc[filt, 'invalidity_reasons'] = (df.loc[filt, 'invalidity_reasons']
                                        .apply(maintain_invalidity_reasons,
                                               args=('another reason',)))
 

вы получите

    Col          invalidity_reasons
0    0  [a reason, another reason]
1    1            [another reason]
2    2            [another reason]
3    3                            
4    4                            
 

Это как-то похоже на то, что вы ищете?

Комментарии:

1. да, это то, что мне было нужно. Я думаю, что большая часть моей проблемы заключалась в том, что у меня не было аргумента в моей функции для представления самой серии ( current_reasons в вашей функции). Спасибо за ваше терпение и помощь!