Как проверить столбец на значение str, определить, является ли другой столбец меньше/больше [x] возвращаемого логического значения во вновь созданном столбце

#python #dataframe #if-statement #filter #boolean

Вопрос:

У меня есть фрейм данных, который выглядит так

продукт Продолжительность
замена шин 01:16:51
замена масла 05:06:00
замена шин 02:03:04
замена масла 06:23:14
замена масла 03:40:27

Я хочу создать новый столбец, который возвращает логическое значение на основе 2 столбцов

продукт Продолжительность duration_bool
замена шин 01:16:51 Правда
замена масла 01:06:00 Правда
замена шин 04:03:04 Ложный
замена масла 02:23:14 Ложный
замена масла 03:40:27 Ложный

Является ли это правильным способом фактического использования функции в кадре данных? Мне трудно понять, как это на самом деле выполняет то, что мне нужно.

 def sla_bool_checker(my_var):

    #check if product is a tire change, if it is, check if duration is under 4 hours and return the Boolean in the new column

    if df['product'] == 'tire change' :
        df['duration_bool'] = df['duration'] < pd.Timedelta(4, unit='h')

    #check if product is a oil change, if it is, check if duration is under 2 hours and return the Boolean

    elif df['product'] == 'oil change' :
        df['duration_bool'] < pd.Timedelta(2, unit='h')
 

Я не знаю, чего мне не хватает, но это ошибка кода.

 ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
 

Ответ №1:

Создайте логический массив на основе ваших условий и назначьте его новому столбцу.

 df['duration'] = df['duration'].apply(pd.Timedelta) # make sure duration has a dtype of Timedelta

df['duration_bool'] = ((df['product'] == 'tire change') amp; (df['duration'] < pd.Timedelta(4, unit='h'))) | 
((df['product'] == 'oil change') amp; (df['duration'] < pd.Timedelta(2, unit='h')))

       product        duration  duration_bool
0  tire change 0 days 01:16:51           True
1   oil change 0 days 05:06:00          False
2  tire change 0 days 02:03:04           True
3   oil change 0 days 06:23:14          False
4   oil change 0 days 03:40:27          False
 

что это значит

((df['product'] == 'tire change') amp; (df['duration'] < pd.Timedelta(4, unit='h'))) где продукт равен замене шин, а продолжительность составляет менее 4 часов.

| или

((df['product'] == 'oil change') amp; (df['duration'] < pd.Timedelta(2, unit='h'))) где продукт равен замене масла, а продолжительность составляет менее 2 часов

Ответ №2:

Во-первых, durations в ваших двух примерах не совпадают, это затрудняет сравнение входных и выходных результатов. Пожалуйста, проверьте это в следующий раз. Тогда вы можете использовать:

 df.loc[df["product"] == "tire change", "duration_bool"] = pd.to_timedelta(df["duration"]) < pd.Timedelta(4, unit="h")
df.loc[df["product"] == "oil change", "duration_bool"] = pd.to_timedelta(df["duration"]) < pd.Timedelta(2, unit="h")
 

Это напрямую устанавливает значения строки duration_bool как результат pd.Timedelta(...) функции, но pd.to_timedelta(...) гарантирует, что это временная шкала, с которой нужно сравнивать.
Это заводит тебя:

 |    | product     | duration   | duration_bool   |
|---:|:------------|:-----------|:----------------|
|  0 | tire change | 01:16:51   | True            |
|  1 | oil change  | 01:06:00   | True            |
|  2 | tire change | 04:03:04   | False           |
|  3 | oil change  | 02:23:14   | False           |
|  4 | oil change  | 03:40:27   | False           |
 

Ответ №3:

Что я выяснил, так это то, что мне нужно было сделать return оговорку в своем def sla_bool_checker . Возвращаемое значение затем необходимо было применить к моему фрейму данных с помощью apply . Я все еще не могу понять, как именно apply это работает, но это сработало, я хотел бы иметь более глубокое объяснение для тех, кому оно нужно.

Я, вероятно, должен был использовать np.where() (все еще неясно, как это сделать), но ответ @it_is_chris на самом деле тоже хорошо сработал для меня! (спасибо, Крис)

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

вот код, который я использовал.

 def sla_bool_checker(my_var):
    #check if product is a tire change, if it is, check if duration is under 4 hours and return the Boolean in new column
    if my_var['product'] == 'tire change' :
        return my_var['duration'] < pd.Timedelta(4, unit='h')
    #check if product is an oil change, if it is, check if duration is under 24 hours and return the Boolean
    elif my_var['product'] == 'oil change' :
        return my_var['duration'] < pd.Timedelta(2, unit='h')
 

затем я использовал

 df['duration_bool'] = df.apply(sla_bool_checker, axis=1)     
df
 

в результате чего

продукт Продолжительность duration_bool
0 замена шин 01:16:51 Правда
1 замена масла 01:06:00 Правда
2 замена шин 04:03:04 Ложный
3 замена масла 02:23:14 Ложный
4 замена масла 03:40:27 Ложный

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

1. Если какой-либо из ответов помог вам или дал новые идеи, авторы высоко оценят, если вы дадите положительный отзыв. Или примите ответ. Спасибо!