为了账号安全,请及时绑定邮箱和手机立即绑定

是否有一种有效的方法来检查列是否具有混合 dtypes?

是否有一种有效的方法来检查列是否具有混合 dtypes?

茅侃侃 2021-09-14 21:07:08
考虑np.random.seed(0)s1 = pd.Series([1, 2, 'a', 'b', [1, 2, 3]])s2 = np.random.randn(len(s1))s3 = np.random.choice(list('abcd'), len(s1))df = pd.DataFrame({'A': s1, 'B': s2, 'C': s3})df           A         B  C0          1  1.764052  a1          2  0.400157  d2          a  0.978738  c3          b  2.240893  a4  [1, 2, 3]  1.867558  a列“A”具有混合数据类型。我想想出一个非常快速的方法来确定这一点。它不会像检查是否那样简单type == object,因为这会将“C”识别为误报。我可以想到这样做df.applymap(type).nunique() > 1A     TrueB    FalseC    Falsedtype: bool但是type在上面调用applymap非常慢。特别是对于较大的框架。%timeit df.applymap(type).nunique() > 13.95 ms ± 88 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)我们能做得更好吗(也许用 NumPy)?如果你的论点足够有说服力,我可以接受“不”。:-)
查看完整描述

3 回答

?
Qyouu

TA贡献1786条经验 获得超11个赞

在熊猫中,infer_dtype()这可能会有所帮助。


用 Cython 编写(代码链接),它返回一个字符串,总结了传递对象中的值。它在 Pandas 的内部结构中被大量使用,所以我们可以合理地期望它在设计时考虑到了效率。


>>> from pandas.api.types import infer_dtype

现在,A 列是整数和其他一些类型的混合:


>>> infer_dtype(df.A)

'mixed-integer'

B列的值都是浮动类型:


>>> infer_dtype(df.B)

'floating'

C列包含字符串:


>>> infer_dtype(df.B)

'string'

混合值的一般“catchall”类型只是“混合”:


>>> infer_dtype(['a string', pd.Timedelta(10)])

'mixed'

浮点数和整数的混合是“混合整数浮点数”:


>>> infer_dtype([3.141, 99])

'mixed-integer-float'

为了使您在问题中描述的功能,一种方法可能是创建一个函数来捕获相关的混合案例:


def is_mixed(col):

    return infer_dtype(col) in ['mixed', 'mixed-integer']

然后你有:


>>> df.apply(is_mixed)

A     True

B    False

C    False

dtype: bool


查看完整回答
反对 回复 2021-09-14
?
波斯汪

TA贡献1811条经验 获得超4个赞

这是一种方法,它利用了在 Python3 中无法比较不同类型的事实。这个想法是运行max数组,作为内置函数应该相当快。它确实短路。


def ismixed(a):

    try:

        max(a)

        return False

    except TypeError as e: # we take this to imply mixed type

        msg, fst, and_, snd = str(e).rsplit(' ', 3)

        assert msg=="'>' not supported between instances of"

        assert and_=="and"

        assert fst!=snd

        return True

    except ValueError as e: # catch empty arrays

        assert str(e)=="max() arg is an empty sequence"

        return False

但是,它不会捕获混合数字类型。此外,不支持比较的对象可能会导致此问题。


但它相当快。如果我们去掉所有pandas开销:


v = df.values


list(map(is_mixed, v.T))

# [True, False, False]

timeit(lambda: list(map(ismixed, v.T)), number=1000)

# 0.008936170022934675

比较


timeit(lambda: list(map(infer_dtype, v.T)), number=1000)

# 0.02499613002873957


查看完整回答
反对 回复 2021-09-14
  • 3 回答
  • 0 关注
  • 181 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信