Вычесть два столбца даты с заданным условием в другом столбце?

#python #python-3.x #pandas #dataframe #datetime-format

#python #python-3.x #панды #фрейм данных #datetime-формат

Вопрос:

Фрейм данных (в формате Excel):

      A                      B                        C
1  this 9/20/2020  2:33:59 PM    9/20/2020  2:34:04 PM
2  this 9/17/2020  6:39:19 PM    9/17/2020  6:24:11 PM
3  not  9/22/2020  1:23:45 AM    9/22/2020  1:23:41 AM
4  this 
  

Я пытаюсь найти разницу между C и B (путем вычисления C-B), но только если в столбце A == ‘this’, чтобы затем поместить эти вычисления в новый столбец D.

Желательно, чтобы это было только в часах, где пробелы здесь не учитываются для вычисления. Столбцы B и C уже правильно отформатированы для даты и времени. Затем я намерен использовать эти номера часов, чтобы сгруппировать их в интервалы дат для составления отчетов.

Вот что у меня есть до сих пор:

 df = pd.read_excel('df.xlsx')
print(df)

# df['D'] = (df['C']-df['B'])

df.loc[df['A'].eq('this'), 'D'] = (df['C']-df['B'])
  

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

1. Что не так с вашим кодом сейчас?

2. @QuangHoang Я не вижу столбец D при печати df

3. покажите пример того, как вы хотите, чтобы это выглядело

Ответ №1:

Вероятно, есть более элегантное решение этой проблемы, но вот одно из них, использующее понимание списка.

 # Create some data
df_arr = [["this",4.0,6.0], ["this", 5.0, 9.0], ["not", 10.0, 12.0], ["this", 14.0, 20.0]]

# Initiate DataFrame
df = pd.DataFrame(df_arr, columns = ["A", "B", "C"])
  

Фрейм данных:

 ┌───┬──────┬──────┬──────┐
│   │  A   │  B   │  C   │
├───┼──────┼──────┼──────┤
│ 0 │ this │  4.06.0 │
│ 1 │ this │  5.09.0 │
│ 2not10.012.0 │
│ 3 │ this │ 14.020.0 │
└───┴──────┴──────┴──────┘
  

Используйте понимание списка 1 или 2 (оба выводят одинаковые значения).

  • Решение 1. Непосредственно выберите, какие столбцы для итерации, и используйте «zip ()»
  • Решение 2. Перебор строк в DataFrame с помощью «.iterrows()»
 import numpy as np
# List comprehension 1
df["D1"] = [(val_c - val_b) if val_a == "this" else
            np.nan for val_a, val_b, val_c in zip(df["A"], df["B"], df["C"])] 

# OR

# List comprehension 2
df["D2"] = [(row[2] - row[1]) if row[0] == "this" else
            np.nan for idx, row in df.iterrows()] 

  

Результат:

 
┌───┬──────┬──────┬──────┬─────┬─────┐
│   │  A   │  B   │  C   │ D1  │ D2  │
├───┼──────┼──────┼──────┼─────┼─────┤
│ 0 │ this │  4.06.02.02.0 │
│ 1 │ this │  5.09.04.04.0 │
│ 2not10.012.0 │ NaN │ NaN │
│ 3 │ this │ 14.020.06.06.0 │
└───┴──────┴──────┴──────┴─────┴─────┘

  

Естественно, вы можете заменить значение «np.nan» на другие, когда столбец «A» равен «not»

Ответ №2:

Попробуйте numpy.where(condition, [x, y])
Где condition True, yield x , в противном случае yield y

 import pandas as pd
import numpy as np

# load your DataFrame

df['D'] = np.where(df.A == 'this', df.C - df.B, np.nan)

print(df)
      A                   B                   C                 D
0  this 2020-09-20 14:33:59 2020-09-20 14:34:04   0 days 00:00:05
1  this 2020-09-17 18:39:19 2020-09-17 18:24:11 -1 days  23:44:52
2   not 2020-09-22 01:23:45 2020-09-22 01:23:41               NaT

  

Значения внутри столбца D становятся timedelta (разница между двумя объектами datetime)