Пожалуйста, рассмотрите этот простой фрейм данных:
df = pd.DataFrame({'x': [1, 2, 3, 4, 10]}, index = range(5))
df:
x
0 1
1 2
2 3
3 4
4 10
Некоторые индексы:
ff_idx = [1, 2]
sd_idx= [3, 4]
Один из способов создания нового столбца путем фильтрации df на основе приведенных выше индексов:
df['ff_sd_indicator'] = np.nan
df['ff_sd_indicator'][df.index.isin(ff_idx)] = 'ff_count'
df['ff_sd_indicator'][df.index.isin(sd_idx)] = 'sd_count'
Другой способ сделать то же самое:
df['ff_sd_indicator2'] = np.select([df.index.isin(ff_idx) , df.index.isin(sd_idx)], ['ff_count','sd_count' ], default=np.nan)
Обратите внимание: хотя значения ff_sd_indicator
и ff_sd_indicator2
, естественно, одинаковы, пропущенные значения печатаются по-разному (NaN или nan):
df:
x ff_sd_indicator ff_sd_indicator2
0 1 NaN nan
1 2 ff_count ff_count
2 3 ff_count ff_count
3 4 sd_count sd_count
4 10 sd_count sd_count
Меня не волнуют разные отпечатки, но, что удивительно, пропущенные значения не отображаются в выводе:
df['ff_sd_indicator'].value_counts()
который:
ff_sd_indicator
ff_count 2
sd_count 2
Но они появляются в выводе:
df['ff_sd_indicator2'].value_counts()
который:
ff_sd_indicator2
ff_count 2
sd_count 2
nan 1
Итак, что здесь происходит с тем, что value_counts() не считает пропущенные значения в ff_sd_indicator
, хотя они были созданы тем же np.nan, что и недостающие значения в ff_sd_indicator2
?
Редактировать:
df.info()
:
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 x 5 non-null int64
1 ff_sd_indicator 5 non-null object
2 ff_sd_indicator2 5 non-null object
@akuiper, нет, оба являются объектами. Отредактировал вопрос.
По умолчанию value_counts отбрасывает NaN, чего можно избежать, установив dropna=False
:
df['ff_sd_indicator'].value_counts(dropna=False)
ff_sd_indicator
ff_count 2
sd_count 2
NaN 1
Name: count, dtype: int64
Если вы проверите вывод:
np.select([df.index.isin(ff_idx) , df.index.isin(sd_idx)],
['ff_count','sd_count'], default=np.nan)
Однако вы увидите, что у вас не NaN, а строка:
array(['nan', 'ff_count', 'ff_count', 'sd_count', 'sd_count'],
dtype='<U32')
Таким образом, значение не удаляется автоматически.
Ааа, ты совершенно прав. Но почему np.select создает значения по умолчанию в виде строки, в то время как пользователь указал default=np.nan
(то есть с плавающей точкой), хотя он мог бы сделать default='nan', если бы ему нужна строка nan? Разве это не недостаток функции np.select?
@Saeed, потому что массивы numpy имеют однородный тип dtype, когда несовместимые типы dtype смешаны, numpy может попытаться привести к понижению. Точно так же, если вы присвоите число с плавающей запятой целочисленному массиву, будет использоваться только целая часть. Обратите внимание, что вы можете создавать массивы объектов, но это должно быть сделано явно.
Кстати, меня смутило то, что я пытался заменить эти пропущенные значения на 0 на df['ff_sd_indicator2'].fillna(0)
, но, конечно, этого не получалось, потому что это были строки nan.
Каковы типы двух столбцов? Я считаю, что у вас есть столбец типа объекта и столбец строкового типа.