Выберите строки с максимальным количеством столбцов, отличных от na, из непрерывного набора из n строк

#python #pandas #datetime

Вопрос:

У меня есть df с индексом времени и несколько столбцов с числовыми значениями, но в некоторых случаях они также содержат пропущенные значения. Например:

 timeindex   ColA    ColB    ColC
00:02:00      454    436    4334
00:04:00             653
00:06:00      3423   4354 
00:08:00      3432
00:10:00      2343
00:12:00     32432          23423
 

Я хотел бы создать подмножество фрейма данных таким образом, чтобы для каждой последовательной группы из 3 строк он выбирал строку с наименьшим количеством пропущенных значений.
Таким образом, для приведенного выше df, subsetdf будет выглядеть так:

 timeindex   ColA    ColB    ColC
00:02:00      454    436    4334
00:12:00     32432          23423
 

Можете ли вы посоветовать, как я могу этого добиться, пожалуйста

Ответ №1:

Используйте df.filter для выбора столбцов, проверки наличия пустых строк sum на оси 1, а затем, наконец groupby.idxmax

 idx = (df.assign(count=df.filter(like="Col").notnull().sum(1))
         .groupby(np.arange(len(df))//3)["count"].idxmax())

print (df.loc[idx])

  timeindex   ColA ColB   ColC
0  00:02:00    454  436   4334
5  00:12:00  32432       23423
 

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

1. Ошибка типа: не удается выполнить floordiv с этим типом индекса: Индекс

2. Затем используйте np.arange(len(df))//3 вместо df.index//3 .

3. По какой-то причине на выходе не выбираются строки с наименьшими столбцами нулевого значения… это просто выбор 3-го ряда из каждых 3 групп строк

4. Пустое значение равно nan

5. Тогда зачем вам предоставлять образец df с пустыми значениями, как указано выше? Было бы намного проще, если бы это была просто нэн.

Ответ №2:

 # split the dataframe into groups of 3
df_dict = {n: df.iloc[n:n 3, :] 
           for n in range(0, len(df), 3)}

# find indexes of the minimum number of None for each group
mask = []
for g in df_dict.values():
    mask.append((g.isnull().sum(axis=1)).idxmin())

# keep only those rows
df.iloc[mask]
 

если бы ты хотел опустошить, а не никого:

Замените эту строку:

 mask.append((g.isnull().sum(axis=1)).idxmin())
 

По этому ряду:

 mask.append((g.eq('').sum(axis=1)).idxmin())