在Pandas DataFrame中检查dtype时的警告


问题内容

这个答案的指导下,我开始根据其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)

输出:
在此处输入图片说明

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

在此处输入图片说明

几乎一切都很好,但是此测试代码产生两个问题:

  1. 这里最奇怪的是pd.api.types.is_string_dtypecategorydtype上触发。这是为什么?应该将其视为“预期”行为吗?
  2. 为什么is_string_dtypeis_object_dtype彼此开火?这是可以预料的,因为即使在.dtypes这两种类型中都将记为object,但是最好是一步一步地弄清楚它。

附:奖金问题-我以为熊猫在构建新版本时应该通过其内部测试是正确的吗(例如测试代码中的df_types,但不是用“红色涂成”而是“记录有关错误的信息”)?

编辑:熊猫版本0.24.2


问题答案:

这可以归结为is_string_dtype一个相当宽松的检查,甚至在实现上甚至有一个TODO注释使其更加严格,并链接到Issue#15585

这项检查不严格的原因是因为中没有专用的字符串dtype
pandas,而是仅使用objectdtype存储了字符串,而dtype确实可以存储任何内容。这样,更严格的检查可能会引入性能开销。

要回答您的问题:

  1. CategoricalDtype.kind设置为的结果'O',这是宽松检查之一is_string_dtype。鉴于待办事项说明,这种情况将来可能会改变,所以这不是我要依靠的。

  2. 由于字符串存储为objectdtype,因此可以is_object_dtype在字符串上触发,并且我认为这种行为是可靠的,因为在不久的将来几乎可以肯定不会改变实现。由于对dtype.kindin的依赖,情况恰恰相反is_string_dtype,它具有与上述类别相同的警告。

  3. 是的,pandas有一个测试套件,它将针对创建的每个PR在各种CI服务上自动运行。测试套件包括与您正在执行的检查类似的检查。

要添加一个与切线相关的注释:有一个名为的库fletcher,该库使用Apache
Arrow以与兼容的方式实现本机字符串类型pandas。它仍在开发中,目前可能不支持所有支持的字符串操作pandas