Фильтрация строк данных по часам и максимальной дате - PullRequest
6 голосов
/ 19 апреля 2019

внутри фрейма данных. Я хочу отфильтровать все строки из некоторой «Серии» по часам / ключам и равным максимальной дате.

У меня есть рабочий кусок кода, но мне интересно, нет ли чего-то более компактного или элегантного, чтобы достичь того же?

df = pd.read_csv("./example.csv")
df["Date"] = pd.to_datetime(df["Date"])
Keys2Filter = (1, 2)
df

...
    Key Date    Value
0   1   2019-04-17 00:00:00 1
1   1   2019-04-17 01:00:00 2
2   1   2019-04-17 02:00:00 3
3   1   2019-04-17 00:00:00 4
4   1   2019-04-17 01:00:00 5
5   1   2019-04-17 00:00:00 7
6   2   2019-04-17 01:00:00 8
7   2   2019-04-17 02:00:00 9
8   2   2019-04-17 00:00:00 9
9   2   2019-04-17 01:00:00 9
10  3   2019-04-17 01:00:00 9
11  3   2019-04-17 01:00:00 9
...

if (len(Keys2Filter)):
    dfMax = df[df.Key.isin(Keys2Filter)]  
    dfMax = dfMax.groupby(by=["Key", dfMax.Date.dt.hour]).max()
    dfMax.index.names = ["Key", "Hour"]
    dfMax = dfMax.reset_index()
    df = df[~df.Key.isin(Keys2Filter)].append(dfMax.drop(columns=['Hour'])) 

df   

Key Date    Value
10  3   2019-04-17 01:00:00 9
11  3   2019-04-17 01:00:00 9
0   1   2019-04-17 00:00:00 7
1   1   2019-04-17 01:00:00 5
2   1   2019-04-17 02:00:00 3
3   2   2019-04-17 00:00:00 9
4   2   2019-04-17 01:00:00 9
5   2   2019-04-17 02:00:00 9

Ответы [ 2 ]

3 голосов
/ 19 апреля 2019

IIUC с использованием transform и isin, преобразование получит максимум для всех групповых потоков со строкой, затем мы используем isin, если значение не находится в Keys2Filter, тогда мы должны выбрать, если оно находится в Keys2Filter, который вернет False при ~isin, затем мы проверим 2-е условие, если эта строка выдает максимальное значение группы, то мы все равно выбираем его.

s=df.groupby([df.Key,df.Date.dt.strftime('%Y-%m-%d %H')])['Value'].transform('idxmax')
Keys2Filter = (1, 2)
df=df.loc[~df.Key.isin(Keys2Filter)|df.index.eq(s)].copy()#avoid the copy error 
df
Out[991]: 
    Key                Date  Value
2     1 2019-04-17 02:00:00      3
4     1 2019-04-17 01:00:00      5
5     1 2019-04-17 00:00:00      7
7     2 2019-04-17 02:00:00      9
8     2 2019-04-17 00:00:00      9
9     2 2019-04-17 01:00:00      9
10    3 2019-04-17 01:00:00      9
11    3 2019-04-17 01:00:00      9

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

3 голосов
/ 19 апреля 2019

Решение хорошее, только небольшое упрощение - логическая маска должна быть привязана к переменной m, а для инвертирования используется ~, также используется двойное DataFrame.reset_index - сначала для удаления второго уровня, а затем для второгодля столбца из индекса:

m = df.Key.isin(Keys2Filter)
df = (df[~m].append(df[m].groupby(by=["Key", df.Date.dt.hour])
                         .max()
                         .reset_index(level=1, drop=True)
                         .reset_index()))

print (df)
    Key                Date  Value
10    3 2019-04-17 01:00:00      9
11    3 2019-04-17 01:00:00      9
0     1 2019-04-17 00:00:00      7
1     1 2019-04-17 01:00:00      5
2     1 2019-04-17 02:00:00      3
3     2 2019-04-17 00:00:00      9
4     2 2019-04-17 01:00:00      9
5     2 2019-04-17 02:00:00      9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...