如何确定一个列/变量是否是数字熊猫/NumPy?

有没有更好的方法来确定 Pandas和/或 NumPy中的变量是否是 numeric

我有一个自定义的 dictionary,键为 dtypes,值为 numeric/not

153099 次浏览

这是一种仅返回数值类型数据的伪内部方法

In [27]: df = DataFrame(dict(A = np.arange(3),
B = np.random.randn(3),
C = ['foo','bar','bah'],
D = Timestamp('20130101')))


In [28]: df
Out[28]:
A         B    C                   D
0  0 -0.667672  foo 2013-01-01 00:00:00
1  1  0.811300  bar 2013-01-01 00:00:00
2  2  2.020402  bah 2013-01-01 00:00:00


In [29]: df.dtypes
Out[29]:
A             int64
B           float64
C            object
D    datetime64[ns]
dtype: object


In [30]: df._get_numeric_data()
Out[30]:
A         B
0  0 -0.667672
1  1  0.811300
2  2  2.020402

根据@jaime 在评论中的回答,您需要检查 .dtype.kind中感兴趣的列

>>> import pandas as pd
>>> df = pd.DataFrame({'numeric': [1, 2, 3], 'not_numeric': ['A', 'B', 'C']})
>>> df['numeric'].dtype.kind in 'biufc'
>>> True
>>> df['not_numeric'].dtype.kind in 'biufc'
>>> False

注意: biufc的含义: b bool,i int (有符号) ,u无符号 int,f float,c复数。参见 https://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.kind.html#numpy.dtype.kind

您可以使用 np.issubdtype来检查 dtype 是否是 np.number的子 dtype:

np.issubdtype(arr.dtype, np.number)  # where arr is a numpy array
np.issubdtype(df['X'].dtype, np.number)  # where df['X'] is a pandas Series

这对 numpy 的 dtype 有效,但对于特定于熊猫的类型(如 pd)就失败了。类作为托马斯 知道了。如果您正在使用来自大熊猫的分类 is_numeric_dtype函数,那么它是比 np.issubdtype 更好的选择。

df = pd.DataFrame({'A': [1, 2, 3], 'B': [1.0, 2.0, 3.0],
'C': [1j, 2j, 3j], 'D': ['a', 'b', 'c']})
df
Out:
A    B   C  D
0  1  1.0  1j  a
1  2  2.0  2j  b
2  3  3.0  3j  c


df.dtypes
Out:
A         int64
B       float64
C    complex128
D        object
dtype: object

np.issubdtype(df['A'].dtype, np.number)
Out: True


np.issubdtype(df['B'].dtype, np.number)
Out: True


np.issubdtype(df['C'].dtype, np.number)
Out: True


np.issubdtype(df['D'].dtype, np.number)
Out: False

对于多个列,可以使用 np.vectorize:

is_number = np.vectorize(lambda x: np.issubdtype(x, np.number))
is_number(df.dtypes)
Out: array([ True,  True,  True, False], dtype=bool)

至于选择,熊猫现在有 select_dtypes:

df.select_dtypes(include=[np.number])
Out:
A    B   C
0  1  1.0  1j
1  2  2.0  2j
2  3  3.0  3j

你也可以试试:

df_dtypes = np.array(df.dtypes)
df_numericDtypes= [x.kind in 'bifc' for x in df_dtypes]

它返回一个布尔值列表: 如果是数字,返回 True; 如果不是,返回 False

pandas 0.20.2中,你可以做:

import pandas as pd
from pandas.api.types import is_string_dtype
from pandas.api.types import is_numeric_dtype


df = pd.DataFrame({'A': ['a', 'b', 'c'], 'B': [1.0, 2.0, 3.0]})


is_string_dtype(df['A'])
>>>> True


is_numeric_dtype(df['B'])
>>>> True

只检查列中的一个值的类型怎么样? 我们总是有这样的东西:

isinstance(x, (int, long, float, complex))

当我试图检查下面数据框中的列的数据类型时,我得到的是“ object”而不是我期望的数字类型:

df = pd.DataFrame(columns=('time', 'test1', 'test2'))
for i in range(20):
df.loc[i] = [datetime.now() - timedelta(hours=i*1000),i*10,i*100]
df.dtypes


time     datetime64[ns]
test1            object
test2            object
dtype: object

当我这样做时,它似乎给了我准确的结果:

isinstance(df['test1'][len(df['test1'])-1], (int, long, float, complex))

报税表

True

只要添加到所有其他答案,人们还可以使用 df.info()得到什么数据类型的每一列。

熊猫有 select_dtype功能。你可以很容易地过滤你的专栏在 第64章,和 Float64像这样:

df.select_dtypes(include=['int64','float64'])

可以检查给定列是否包含数值或不使用 dtype

numerical_features = [feature for feature in train_df.columns if train_df[feature].dtypes != 'O']

注意: “ O”应该是大写

假设你想保持你的数据在相同的类型,我发现以下工作类似于 df._get_numeric_data():

df = pd.DataFrame({'A': ['a', 'b', 'c'], 'B': [1.0, 2.0, 3.0],
'C': [4.0, 'x2', 6], 'D': [np.nan]*3})


test_dtype_df = df.loc[:, df.apply(lambda s: s.dtype.kind in 'biufc')]
test_dtype_df.shape == df._get_numeric_data().shape
Out[1]: True

但是,如果您想测试一个序列是否正确转换,可以使用“忽略”:

df_ = df.copy().apply(pd.to_numeric, errors='ignore')
test_nmr_ignore = df_.loc[:, df_.apply(lambda s: s.dtype.kind in 'biufc')]


display(test_nmr_ignore)
test_nmr_ignore.shape == df._get_numeric_data().shape,\
test_nmr_ignore.shape == df_._get_numeric_data().shape,\
test_nmr_ignore.shape
B   D
0  1.0 NaN
1  2.0 NaN
2  3.0 NaN
Out[2]: (True, True, (3, 2))

最后,在混合使用某些数据的情况下,可以将 coercepd.to_numeric函数一起使用,然后删除完全用 np.nan值填充的列。

df_ = df.copy().apply(pd.to_numeric, errors='coerce')
test_nmr_coerce = df_.dropna(axis=1, how='all')
display(test_nmr_coerce)
B    C
0  1.0  4.0
1  2.0  NaN
2  3.0  6.0

为了准确起见,您可能必须确定原始数据中的哪些列是 np.nan值。我将原始的 np.nan列与转换后的数据 df_合并在一起:

nacols = [c for c in df.columns if c not in df.dropna(axis=1, how='all').columns]
display(pd.merge(test_nmr_coerce,
df[nacols],
right_index=True, left_index=True))
B    C   D
0  1.0  4.0 NaN
1  2.0  NaN NaN
2  3.0  6.0 NaN