首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重复小于等于算法

问重复小于等于算法
EN

Stack Overflow用户
提问于 2017-10-15 05:07:50
回答 2查看 61关注 0票数 0

我知道一个简单的for-loopy方法来解决这个问题,但是我正在寻找一个更好的算法(主要是为了学习)。这个任务需要的不是关键任务)。我有一组可变长度的pandas.Series,所以这必须是动态的。目标是从集合中获取一个Series,并将其应用到DataFrame的一个列中,其中包含大量的观察结果。Series的名称是它应该应用到的DataFrame列的名称。应用程序操作是逐次小于等于的,因此基本上:

  1. 按降序对序列排序
  2. 对于对应的DataFrame列中小于或等于Series中的第一个值的所有值,指定Series中第一个值的索引。
  3. 重复,直到级数中的所有值都用完为止。

下面是一个玩具示例,只适用于一列:

输入:

代码语言:javascript
复制
# DataFrame (length is constant)   |   Series (length can change)
      C1    C2    C3    C4   ...   |         Val
ID                                 |  IDX
 0  0.20  0.30  0.10  0.25   ...   |    A0   0.20
 1  0.15  0.04  0.40  0.30   ...   |    A1   0.55
 2  0.65  0.83  0.88  0.61   ...   |    A2   0.90
 3  0.15  0.55  0.45  0.26   ...   |    A3   1.00
 4  0.78  0.83  0.89  0.12   ...   | name: C1 # (Note name matches column name)
 5  0.84  0.75  0.39  0.80   ...   |
 6  0.99  0.83  0.45  0.16   ...   |
 (more than 10^7 observations, and about 15 columns)

输出:

代码语言:javascript
复制
# DataFrame
    C1    C2    C3    C4   ...
ID
 0  A0  0.30  0.10  0.25   ...
 1  A0  0.04  0.40  0.30   ...
 2  A2  0.83  0.88  0.61   ...
 3  A0  0.55  0.45  0.26   ...
 4  A2  0.83  0.89  0.12   ...
 5  A2  0.75  0.39  0.80   ...
 6  A3  0.83  0.45  0.16   ...

同样对于C2,C3..。

我目前的解决方案包括一个在循环中执行greater-than函数应用程序的函数,并使用pandas.DataFrame.transform函数进行调用,如下所示:

代码语言:javascript
复制
def less_thn_eq(col, s):
    op = s.copy()
    for i, v in s.sort_values(ascending=False).iteritems():
        op.loc[s <= v] = i

trans_funcs = dict([(s.name, partial(less_thn_eq, s=s)) for s in series_set])
df.transform(trans_funcs)

补充说明:

  1. DataFrame和Series都是由概率过程产生的,因此所有的值都在间隔(0, 1)中。
  2. Series (如果您还没有注意到)是一个累积质量函数,由s.cumsum()/s.sum()获得
  3. 函数less_thn_eq实际上是一个逆质量函数,它将概率观测转化为实际观测。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-15 06:13:00

您可能需要numpy数字化功能。如果您的玩具示例输出中有错误(“A1”可能应该是“A2”),那么下面的内容将是快速的。

代码语言:javascript
复制
# setup toy example
df = pd.DataFrame( np.array([
 0.20, 0.30, 0.10, 0.25,
 0.15, 0.04, 0.40, 0.30,
 0.65, 0.83, 0.88, 0.61,
 0.15, 0.55, 0.45, 0.26,
 0.78, 0.83, 0.89, 0.12,
 0.84, 0.75, 0.39, 0.80,
 0.99, 0.83, 0.45, 0.16]).reshape(7,4), columns=['C1', 'C2', 'C3', 'C4'])
bins = pd.Series ([0.20, 0.55, 0.90, 1.00], index=['A0', 'A1', 'A2', 'A3'])

# perform digitization
eps = 10**-7
bin_indices = pd.Series(bins.index)
indices = np.digitize(df, bins+eps)
(bin_indices[indices.flatten()]).reshape( df.shape )
Out[94]:
array([['A0', 'A1', 'A0', 'A1'],
       ['A0', 'A0', 'A1', 'A1'],
       ['A2', 'A2', 'A2', 'A2'],
       ['A0', 'A1', 'A1', 'A1'],
       ['A2', 'A2', 'A2', 'A0'],
       ['A2', 'A2', 'A1', 'A2'],
       ['A3', 'A2', 'A1', 'A0']], dtype=object)
票数 2
EN

Stack Overflow用户

发布于 2017-10-15 05:54:21

设置:

代码语言:javascript
复制
import pandas as pd
import numpy as np
s = pd.Series([0.20,0.55,0.90,1.00], index = ['A0','A1','A2','A3'], name = 'C1')
df = pd.DataFrame({'C1':[0.20,0.15,0.65,0.15,0.78,0.84,0.99],
                   'C2':[0.30,0.04,0.83,0.55,0.83,0.75,0.83],
                   'C3':[0.10,0.40,0.88,0.45,0.89,0.39,0.45],
                   'C4':[0.25,0.30,0.61,0.26,0.12,0.80,0.16]},
                  )

你可以把这些列作为矮胖的长条

代码语言:javascript
复制
bounds = s.values
test = df[s.name].values

用广播业进行比较

代码语言:javascript
复制
mask = test[:, None] <= bounds

找出指数

代码语言:javascript
复制
new = mask.argmax(axis = 1)

将数组索引与系列索引一起使用并分配

代码语言:javascript
复制
df[s.name] = s.index[new]


>>> df
   C1    C2    C3    C4
0  A0  0.30  0.10  0.25
1  A0  0.04  0.40  0.30
2  A2  0.83  0.88  0.61
3  A0  0.55  0.45  0.26
4  A2  0.83  0.89  0.12
5  A2  0.75  0.39  0.80
6  A3  0.83  0.45  0.16
>>>

如果您想在整个DataFrame上使用Series执行该操作

代码语言:javascript
复制
bounds = s.values
mask = df.values[..., None] <= bounds
new = mask.argmax(axis = 2)
df[df.columns] = s.index[new]

只有在对系列值进行排序的情况下,这才能工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46751910

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档