New*_*ler 6 numpy offset pandas
考虑以下 pd.DataFrame
import numpy as np
import pandas as pd
start_end = pd.DataFrame([[(0, 3), (4, 5), (6, 12)], [(7, 10), (11, 90), (91, 99)]])
values = np.random.rand(1, 99)
Run Code Online (Sandbox Code Playgroud)
的start_end是一个pd.DataFrame形状(X, Y),其中每个值是内部的元组(start_location, end_location)中的values矢量。另一种说法是特定单元格中的值是不同长度的向量。
题
如果我想找到 中每个单元格的向量值的平均值(例如),pd.DataFrame我该如何以一种具有成本效益的方式做到这一点?
我设法用一个.apply函数实现了这一点,但速度很慢。
我想我需要找到某种方法将它呈现在numpy数组中,然后将其映射回 2d 数据框,但我不知道如何。
笔记
泛化问题
更一般地说,我这是一个反复出现的问题,即如何制作 3d 数组,其中一个维度的长度与通过某些转换函数(平均值、最小值等)与 2d 矩阵的长度不相等。
查看您的示例数据:
In [64]: start_end
Out[64]:
0 1 2
0 (1, 6) (4, 5) (6, 12)
1 (7, 10) (11, 12) (13, 19)
Run Code Online (Sandbox Code Playgroud)
每行确实不重叠,但不是整个数据集。
现在,我们np.ufunc.reduceat为每个切片提供了 ufunc 缩减:
ufunc(ar[indices[i]: indices[i + 1]])
Run Code Online (Sandbox Code Playgroud)
只要indices[i] < indices[i+1].
所以,有了ufunc(ar, indices),我们会得到:
[ufunc(ar[indices[0]: indices[1]]), ufunc(ar[indices[1]: indices[2]]), ..]
Run Code Online (Sandbox Code Playgroud)
在我们的例子中,对于每个元组(x,y),我们知道x<y。对于堆叠版本,我们有:
[(x1,y1), (x2,y2), (x3,y3), ...]
Run Code Online (Sandbox Code Playgroud)
如果我们扁平化,它将是:
[x1,y1,x2,y2,x3,y3, ...]
Run Code Online (Sandbox Code Playgroud)
所以,我们可能没有y1<x2,但没关系,因为我们不需要 ufunc 减少对那个和类似的对 : y2,x3。但这没关系,因为可以通过最终输出的步长切片来跳过它们。
因此,我们将有:
# Inputs : a (1D array), start_end (2D array of shape (N,2))
lens = start_end[:,1]-start_end[:,0]
out = np.add.reduceat(a, start_end.ravel())[::2]/lens
Run Code Online (Sandbox Code Playgroud)
np.add.reduceat()部分为我们提供了切片求和。我们需要除以lens进行平均计算。
样品运行 -
In [47]: a
Out[47]:
array([0.49264042, 0.00506412, 0.61419663, 0.77596769, 0.50721381,
0.76943416, 0.83570173, 0.2085408 , 0.38992344, 0.64348176,
0.3168665 , 0.78276451, 0.03779647, 0.33456905, 0.93971763,
0.49663649, 0.4060438 , 0.8711461 , 0.27630025, 0.17129342])
In [48]: start_end
Out[48]:
array([[ 1, 3],
[ 4, 5],
[ 6, 12],
[ 7, 10],
[11, 12],
[13, 19]])
In [49]: [np.mean(a[i:j]) for (i,j) in start_end]
Out[49]:
[0.30963037472653104,
0.5072138121177008,
0.5295464559328862,
0.41398199978967815,
0.7827645134019902,
0.5540688880441684]
In [50]: lens = start_end[:,1]-start_end[:,0]
...: out = np.add.reduceat(a, start_end.ravel())[::2]/lens
In [51]: out
Out[51]:
array([0.30963037, 0.50721381, 0.52954646, 0.413982 , 0.78276451,
0.55406889])
Run Code Online (Sandbox Code Playgroud)
为了完整起见,参考给定的示例,转换步骤是:
# Given start_end as df and values as a 2D array
start_end = np.vstack(np.concatenate(start_end.values))
a = values.ravel()
Run Code Online (Sandbox Code Playgroud)
对于其他有reduceat方法的ufunc ,我们只需替换np.add.reduceat
| 归档时间: |
|
| 查看次数: |
206 次 |
| 最近记录: |