Как заполнить пропущенные значения с помощью различных условий

#python #pandas

Вопрос:

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

  1. Если в Предмете есть одно отсутствующее значение, заполняет отсутствующее значение этого предмета другим значением.
  2. Если в предмете есть два пропущенных значения, то заполните эти пропущенные значения, используя среднюю высоту всех предметов, которые x == ‘AA’

Примечание: В желаемом фрейме данных мы должны иметь одинаковое значение для каждого субъекта.

 df = pd.DataFrame({'Subject': [1,1,2,2,3,3], 'x':['AA','AA','BB','BB','AA','AA'], 'height': [130, np.nan, np.nan, 170, np.nan, np.nan]})

 

введите описание изображения здесь

Вот нужный фрейм данных.

введите описание изображения здесь

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

1. Не могли бы вы предоставить желаемый результат?

2. Я загрузил желаемый результат!

3. но медиана всего столбца равна 150, а не 130? Так почему же вы говорите, что последние 2 строки должны быть заполнены 130?

4. @sophocles Во втором условии операции говорится, что медиана должна приниматься по значениям значений x, которые равны отсутствующим, а не по всему набору данных. Я считаю, что если вы измените свою вторую строку кода на эту, вы получите то, что хочет ОП df.apply(lambda x: x['height'] if x['height'] == np.nan else df[df['x'] == x['x']]['height'].median() , axis=1) .

5. спасибо вам обоим за вашу помощь!

Ответ №1:

Вы можете сначала fillna() использовать сгруппированное ffill() и bfill() , а затем использовать столбец median :

 df.groupby('Subject')['height'].fillna(method='ffill',inplace=True).fillna(method='bfill',inplace=True)
df['height'].fillna(df['height'].median(),inplace=True)
 

Выход:

    Subject   x  height
0        1  AA   130.0
1        1  AA   130.0
2        2  BB   170.0
3        2  BB   170.0
4        3  AA   150.0
5        3  AA   150.0
 

Изменить: Если вы требуете, чтобы медиана принималась за значения значений x, которые равны отсутствующим , а не за весь набор данных, вы можете воспользоваться советом @xicoaio и заменить мою вторую строку df['height'].fillna(df['height'].median(),inplace=True) на:

 df['height'] = df.apply(lambda x: x['height'] if x['height'] == np.nan else df[df['x'] == x['x']]['height'].median() , axis=1)
 

Выход:

    Subject   x  height
0        1  AA   130.0
1        1  AA   130.0
2        2  BB   170.0
3        2  BB   170.0
4        3  AA   130.0
5        3  AA   130.0
 

Ответ №2:

Я бы сделал это в два этапа.

Сначала заполните поля для каждого Subject , у которого есть одно height значение

 df['height_v2'] = np.select([df['height'].isna()], 
                            [df.groupby(['Subject', 'x'])['height'].transform('max')], 
                            default=df['height'])
 

А затем заполните случаи, когда отсутствуют оба значения высоты.
Здесь я предполагаю, что если a Subject есть x=='BB' , мы заполним его на основе медианы BB случаев.

 df['height_final'] = df.groupby('x')['height_v2'].transform(np.median)