Предостережения при проверке dtype в пандах DataFrame - PullRequest
3 голосов
/ 30 мая 2019

Руководствуясь этим ответом, я начал создавать конвейер для обработки столбцов информационного кадра на основе его dtype. Но после получения неожиданного вывода и некоторой отладки я закончил тестовым фреймом данных и тестовой проверкой dtype:

# Creating test dataframe
test = pd.DataFrame({'bool' :[False, True], 'int':[-1,2],'float': [-2.5, 3.4],
                     'compl':np.array([1-1j, 5]),
                     'dt'   :[pd.Timestamp('2013-01-02'), pd.Timestamp('2016-10-20')],
                     'td'   :[pd.Timestamp('2012-03-02')- pd.Timestamp('2016-10-20'),
                              pd.Timestamp('2010-07-12')- pd.Timestamp('2000-11-10')],
                     'prd'  :[pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')],
                     'intrv':pd.arrays.IntervalArray([pd.Interval(0, 0.1), pd.Interval(1, 5)]),
                     'str'  :['s1', 's2'],
                     'cat'  :[1, -1],
                     'obj'  :[[1,2,3], [5435,35,-52,14]]
                    })
test['cat'] = test['cat'].astype('category')
test
test.dtypes

# Testing types
types = list(test.columns)
df_types = pd.DataFrame(np.zeros((len(types),len(types)), dtype=bool),
                        index = ['is_'+el for el in types],
                        columns = types)
for col in test.columns:
    df_types.at['is_bool', col] = pd.api.types.is_bool_dtype(test[col])
    df_types.at['is_int' , col] = pd.api.types.is_integer_dtype(test[col])
    df_types.at['is_float',col] = pd.api.types.is_float_dtype(test[col])
    df_types.at['is_compl',col] = pd.api.types.is_complex_dtype(test[col])
    df_types.at['is_dt'  , col] = pd.api.types.is_datetime64_dtype(test[col])
    df_types.at['is_td'  , col] = pd.api.types.is_timedelta64_dtype(test[col])
    df_types.at['is_prd' , col] = pd.api.types.is_period_dtype(test[col])
    df_types.at['is_intrv',col] = pd.api.types.is_interval_dtype(test[col])
    df_types.at['is_str' , col] = pd.api.types.is_string_dtype(test[col])
    df_types.at['is_cat' , col] = pd.api.types.is_categorical_dtype(test[col])
    df_types.at['is_obj' , col] = pd.api.types.is_object_dtype(test[col])

# Styling func
def coloring(df):
    clr_g = 'color : green'
    clr_r = 'color : red'
    mask = ~np.logical_xor(df.values, np.eye(df.shape[0], dtype=bool))
    # OUTPUT
    return pd.DataFrame(np.where(mask, clr_g, clr_r),
                        index = df.index,
                        columns = df.columns)

# OUTPUT colored
df_types.style.apply(coloring, axis=None)

ВЫВОД: enter image description here

bool                  bool
int                  int64
float              float64
compl           complex128
dt          datetime64[ns]
td         timedelta64[ns]
prd              period[D]
intrv    interval[float64]
str                 object
cat               category
obj                 object

enter image description here

Почти все хорошо, но этот тестовый код вызывает два вопроса:

  1. Самое странное, что pd.api.types.is_string_dtype стреляет на category dtype. Это почему? Должно ли это рассматриваться как «ожидаемое» поведение?
  2. Почему is_string_dtype и is_object_dtype срабатывает на каждом Другой? Это немного ожидаемо, потому что даже в .dtypes оба типа отмечены как object, но было бы лучше, если бы кто-то это уточнить шаг за шагом.

Ps: Бонусный вопрос - прав ли я, думая, что у pandas есть свои внутренние тесты, которые следует пройти при создании нового релиза (например, df_types из тестового кода, но не с «окраской в ​​красный цвет», а «запись информации об ошибках»)

РЕДАКТИРОВАТЬ: версия для панд 0.24.2.

1 Ответ

1 голос
/ 31 мая 2019

Это сводится к тому, что is_string_dtype является довольно слабой проверкой, при реализации даже с примечанием TODO, чтобы сделать его более строгим, ссылка на Issue # 15585 .

Причина, по которой эта проверка не является строгой, заключается в том, что в pandas нет выделенной строки типа dtype, а вместо этого строки просто хранятся с типом object dtype, который действительно может хранить что угодно. Таким образом, более строгая проверка может привести к снижению производительности.

Чтобы ответить на ваши вопросы:

  1. Это результат установки CategoricalDtype.kind на 'O', что является одной из свободных проверок is_string_dtype. Возможно, это изменится в будущем, учитывая примечание TODO, поэтому я бы не стал на это полагаться.

  2. Поскольку строки хранятся как object dtype, имеет смысл для is_object_dtype запускать строки, и я считаю, что это поведение будет надежным, поскольку реализация почти наверняка не изменится в ближайшем будущем. Обратное верно из-за зависимости от dtype.kind в is_string_dtype, которая имеет те же предостережения, что и для категорий, описанных выше.

  3. Да, pandas имеет набор тестов, который будет автоматически запускаться в различных службах CI для каждого созданного PR. Набор тестов включает в себя проверки, аналогичные тем, что вы делаете.

Одно касательное примечание, которое нужно добавить: есть библиотека с именем fletcher, которая использует Apache Arrow для реализации более нативного строкового типа способом, совместимым с pandas. Он все еще находится в стадии разработки и, вероятно, в настоящее время не поддерживает все строковые операции, которые pandas делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...