V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
acone2003
V2EX  ›  Python

问一个数据快速离散化的问题

  •  
  •   acone2003 · 153 天前 · 1927 次点击
    这是一个创建于 153 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我对一个一维向量 Features 进行了分箱操作,得到了每个箱体的右边界如下:NBins=[0.3, 5.4, 7.6, inf],每个箱体指定对应的一个替代值,如[3.5, 7.8, 2.4, 3.6],把向量离散成替代值,就是将所有小于 0.3 的值替换成 3.5 ,在 0.3 至 5.4 之间的替换成 7.8 等等,问一下怎样做速度比较快?
    5 条回复    2022-02-06 20:10:16 +08:00
    necomancer
        1
    necomancer  
       153 天前
    用 numpy.array (pandas.DataFrame)?
    a[a<0.3] =3.5
    a[np.logical_and(a < 5.4, a > 0.3)] = 7.8
    necomancer
        2
    necomancer  
       153 天前
    可以给 NBins 加上左边界然后用 for:
    vals = [3.5, 7.8, ...]
    NBins = [-np.inf, 0.3, 5.4..., np.inf]
    for l, r, val in zip(NBins[:-1], NBins[1:], vals):
    ....a[np.logical_and(a > l, a< r)] = val
    acone2003
        3
    acone2003  
    OP
       152 天前
    谢谢 necomancer ,祝你新年快乐!我现在还没有运行你上边的代码,但是有一个疑问,比如有一个值-1 ,在 a[a<0.3] =3.5 中被替换成了 3.5 ,在随后的 a[np.logical_and(a < 5.4, a > 0.3)]=7.8 中是否又被替换成了 7.8 呢?
    necomancer
        4
    necomancer  
       151 天前
    @acone2003 新年快乐!
    会,这个是我脑残……这个方法大概就是暴力循环
    for f in features:
    ....for val in f:
    ........for l, r, val
    这样,使用 numpy 的索引大概是这个计算量(按大小判定)的两倍,但是 numpy 的各种操作非常快。我觉得这个问题可以通过边界问题搞定,例如 NBins = [a.min(), 0.3, ...., np.inf],然后 vals 减掉一个值 V ,使所有的 vals 都小于 a.min(),即 vals-V < a.min(),然后替换完以后 a = a+V ,这个方法在数组大了以后会比循环快一些,小数组和循环没啥区别。

    不过根据索引也许有个简单的方法,但是 binsize 如果非常不均匀可能需要非常小的 binsize ,你这个箱体 binsize=0.1 是刚好的,先令 NBins=np.array([0.3, ...7.6]),我觉得所以
    a = np.asarray(a/binsize, dtype=np.int64)
    然后生成新的 NBins:
    nvals = np.diff(np.array(NBins/binsize, dtype=np.int64), prepend=0))
    r = np.concatenate([ [val] * n for val, n in zip(vals, nvals)])
    这里 r 会生成 2 个 3.5 ,52 个 7.8,...
    然后处理边界
    a[a<int(NBins[0]/0.1)] = len(r)
    a[a>int(NBins[-1]/0.1)] = len(r)+1
    r = np.append(r, left_bound_val)
    r = np.append(r, right_bound_val)
    然后 r[a] 就是结果。这样的计算量是最小的。不过需要注意两点,一是 NBins 里的值不总大于 0 ,二是很小 binsize 以及变化很急剧的 NBins 会导致一个巨长的数组 r ,也会很麻烦。不过这些可以通过线性变换你的样本和 NBins 一类的方法解决,就看具体情况了。
    niqy1988
        5
    niqy1988  
       145 天前 via Android
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1824 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 16:51 · PVG 00:51 · LAX 09:51 · JFK 12:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.