更改 DataFrame 列类型但使用错误默认值的简单方法?

Set*_*ton 4 python type-conversion pandas

假设我有以下列。

>>> import pandas
>>> a = pandas.Series(['0', '1', '5', '1', None, '3', 'Cat', '2'])
Run Code Online (Sandbox Code Playgroud)

我希望能够将列中的所有数据转换为 type int,并且任何无法转换的元素都应该替换为0.

我当前的解决方案是使用to_numericwith'coerce'选项,用 填充任何NaN内容0,然后转换为int(因为 的存在NaN使得列float而不是int)。

>>> pandas.to_numeric(a, errors='coerce').fillna(0).astype(int)
0    0
1    1
2    5
3    1
4    0
5    3
6    0
7    2
dtype: int64
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以让我一步完成此操作,而不必经历两个中间状态?我正在寻找类似于以下想象选项的东西astype

>>> a.astype(int, value_on_error=0)
Run Code Online (Sandbox Code Playgroud)

piR*_*red 5

选项1

pd.to_numeric(a, 'coerce').fillna(0).astype(int)
Run Code Online (Sandbox Code Playgroud)

选项2

b = pd.to_numeric(a, 'coerce')
b.mask(b.isnull(), 0).astype(int)
Run Code Online (Sandbox Code Playgroud)

选项3

def try_int(x):
    try:
        return int(x)
    except:
        return 0

a.apply(try_int)
Run Code Online (Sandbox Code Playgroud)

选项4

b = np.empty(a.shape, dtype=int)

i = np.core.defchararray.isdigit(a.values.astype(str))

b[i] = a[i].astype(int)
b[~i] = 0

pd.Series(b, a.index)
Run Code Online (Sandbox Code Playgroud)

所有产品

0    0
1    1
2    5
3    1
4    0
5    3
6    0
7    2
dtype: int64
Run Code Online (Sandbox Code Playgroud)

下面的时序
代码

在此输入图像描述

def pir1(a):
    return pd.to_numeric(a, 'coerce').fillna(0).astype(int)

def pir2(a):
    b = pd.to_numeric(a, 'coerce')
    return b.mask(b.isnull(), 0).astype(int)

def try_int(x):
    try:
        return int(x)
    except:
        return 0

def pir3(a):
    return a.apply(try_int)

def pir4(a):
    b = np.empty(a.shape, dtype=int)

    i = np.core.defchararray.isdigit(a.values.astype(str))

    b[i] = a[i].astype(int)
    b[~i] = 0
    return pd.Series(b, a.index)


def alt1(a):
    return pd.to_numeric(a.where(a.str.isnumeric(), 0))

results = pd.DataFrame(
    index=[1, 3, 10, 30, 100, 300, 1000, 3000, 10000],
    columns='pir1 pir2 pir3 pir4 alt1'.split()
)

for i in results.index:
    c = pd.concat([a] * i, ignore_index=True)
    for j in results.columns:
        stmt = '{}(c)'.format(j)
        setp = 'from __main__ import c, {}'.format(j)
        results.set_value(i, j, timeit(stmt, setp, number=10))

results.plot(logx=True, logy=True)
Run Code Online (Sandbox Code Playgroud)