Преобразование str в int с пустыми ячейками pandas

Рейтинг: 2Ответов: 2Опубликовано: 06.04.2023
import pandas as pd

df = pd.DataFrame({'Минимум': [0, 0, 0, 0, 0, 0, 0], 
               'vendor1': ['', '', '65000', '', '14000', '11000', ''], 
               'vendor2': ['22000', '12000', '', '', '15000', '', '71000'], 
               'vendor3': ['', '', '', '', '', '9900', ''], 
               'vendor4': ['23000', '', '', '', '13600', '', '76000']})

Имеется DataFrame df, который имеет типы:

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

Задача состоит в том, что бы в каждой строке от vendor1 до vendor4 включительно найти минимальное значение и вставить его в первый столбец 'Минимум'. Что бы в итоге первый столбец состоял из значений: 22000, 12000, 65000, 0, 13600, 9900, 71000. И сюда логично напрашивается код:

df['Минимум'] = df.loc[:,'vendor1':'vendor4'].min(axis=1)

Но я не могу совладать с типами столбцов и ячеек, т.к. знаний не хватает. Понимаю, что сейчас строки в df не могут иметь параметра минимум и поэтому код не работает, но если все переделать в int то программа ругается на пустые ячейки. Если начать использовать fillna(0).dtype(int) то код фактически работает, но нули мешают. В общем я устал и запутался.

Вопрос.

Подскажите, как в нужных в столбцах (от vendor1 до vendor4) преобразовать типы данных (в int) только заполненных ячеек, и при этом игнорировать пустые ячейки? Ну и в дальнейшем что бы минимальное значение выбиралось из нужного диапазона только в том случае, если ячейка заполнена цифрой.

Иными словами нужно, что бы получилось так:

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

Спасибо.

Ответы

▲ 4Принят

Можно привести в числовому типу с коррекцией ошибок:

df["Минимум"] = df.loc[:,'vendor1':'vendor4'].apply(pd.to_numeric, errors='coerce').astype('Int64').min(axis=1).fillna(0)
   Минимум vendor1 vendor2 vendor3 vendor4
0  22000.0           22000           23000
1  12000.0           12000                
2  65000.0   65000                        
3      0.0                                
4  13600.0   14000   15000           13600
5   9900.0   11000            9900        
6  71000.0           71000           76000

Либо, as per @CrazyElf, можно явно сохранить тип int:

df["Минимум"] = df.loc[:,'vendor1':'vendor4'].apply(pd.to_numeric, errors='coerce').astype('Int64').min(axis=1, numeric_only=True).fillna(0)
   Минимум vendor1 vendor2 vendor3 vendor4
0    22000           22000           23000
1    12000           12000                
2    65000   65000                        
3        0                                
4    13600   14000   15000           13600
5     9900   11000            9900        
6    71000           71000           76000
​```
▲ 3

Для преобразования '' в NaN используем способ mask(df == ''), другие способы есть тут. Для преобразования строковых значений в числа используется pandas.Int64Dtype. Второй строкой, меняем NaN на 0 и конвертируем в целое.

df['Минимум'] = df.loc[:, 'vendor1':'vendor4'].mask(df == '').astype(pd.Int64Dtype()).min(axis=1)
df['Минимум'] = df['Минимум'].fillna(0).astype(int)
df
Out[6]: 
   Минимум vendor1 vendor2 vendor3 vendor4
0    22000           22000           23000
1    12000           12000                
2    65000   65000                        
3        0                                
4    13600   14000   15000           13600
5     9900   11000            9900        
6    71000           71000           76000