我知道一种简单的for
- 循环方式来解决这个问题,但我正在寻找一种更好的算法(主要是为了学习。需要这项任务的任务不是关键任务)。我有一组pandas.Series
,每个都是可变长度的,所以这必须是动态的。目标是从集合中获取Series
,并将其应用于DataFrame
的列,并进行大量观察。 Series
的名称是应该应用的DataFrame
列的名称。应用程序操作是连续的小于等于,所以基本上是:
DataFrame
中第一个值的相应Series
列中的所有值,请指定Series
这是一个玩具示例,只适用于一列:
输入:
# 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)
输出:
# 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
函数调用,如下所示:
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)
附加说明:
DataFrame
和Series
都是由概率流程生成的,因此所有值都将始终位于(0, 1)
Series
(如果您还没有注意到)是一个累积质量函数,由s.cumsum()/s.sum()
less_thn_eq
实际上是一个反质量函数,它将概率观测值转换为实际观察值。答案 0 :(得分:2)
您可能需要numpy数字化功能。如果您的玩具示例输出中存在拼写错误('A1'可能应为'A2'),则以下内容将会很快。
# 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)
答案 1 :(得分:1)
设定:
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]},
)
您可以将列作为numpy ndarrays
bounds = s.values
test = df[s.name].values
按broadcasting进行比较:
mask = test[:, None] <= bounds
new = mask.argmax(axis = 1)
将array indexing与系列&#39;一起使用索引和分配
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执行操作
bounds = s.values
mask = df.values[..., None] <= bounds
new = mask.argmax(axis = 2)
df[df.columns] = s.index[new]
这仅在对Series值进行排序时才有效。