- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我们有一个像这样的 pandas df:
A B C
day1 2.4 2.1 3.0
day2 4.0 3.0 2.0
day3 3.0 3.5 2.5
day4 1.0 3.1 3.0
.....
我想获得所有列的滚动百分位数排名,窗口包含 10 个观察值。以下代码有效但速度很慢:
scores = pd.DataFrame().reindex_like(df).replace(np.nan, '', regex=True)
scores = df.rolling(10).apply(lambda x: stats.percentileofscore(x, x[-1]))
我也试过这个,但它更慢:
def pctrank(x):
n = len(x)
temp = x.argsort()
ranks = np.empty(n)
ranks[temp] = (np.arange(n) + 1) / n
return ranks[-1]
scores = df.rolling(window=10,center=False).apply(pctrank)
有没有更快的解决方案?谢谢
最佳答案
因为你想要单个元素在滚动窗口中的排名,所以你不需要在每一步都进行排序。您可以将最后一个值与窗口中的所有其他值进行比较:
def pctrank_comp(x):
x = x.to_numpy()
smaller_eq = (x <= x[-1]).sum()
return smaller_eq / len(x)
要消除应用开销,您可以使用 slide_tricks 在 NumPy 中重写相同的开销来自 NumPy v1.20:
from numpy.lib.stride_tricks import sliding_window_view
data = df.to_numpy()
sw = sliding_window_view(data, 10, axis=0)
scores_np = (sw <= sw[..., -1:]).sum(axis=2) / sw.shape[-1]
scores_np_df = pd.DataFrame(scores_np, columns=df.columns)
这不包含每列的前 9 个 NaN 值,作为您的解决方案,如果需要,我会把它留给您来解决。
将滑动窗口轴从最后一个轴切换到第一个轴提供了另一个性能改进:
sw = sliding_window_view(data, 10, axis=0).T
scores_np = (sw <= sw[-1:, ...]).sum(axis=0).T / sw.shape[0]
为了进行基准测试,一些具有 1000 行的测试数据:
df = pd.DataFrame(np.random.uniform(0, 10, size=(1000, 3)), columns=list("ABC"))
问题的原始解决方案在 381 毫秒内出现:
%timeit scores = df.rolling(window=10,center=False).apply(pctrank)
381 ms ± 2.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
使用 apply 实现差异化,在我的机器上快 5 倍:
%timeit scores_comp = df.rolling(window=10,center=False).apply(pctrank_comp)
71.9 ms ± 318 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
来自 Cimbali's answer 的 groupby 解决方案, 在我的机器上快 45 倍:
%timeit grouped = pd.concat({n: df.shift(n) for n in range(10)}).groupby(level=1); scores_grouped = grouped.rank(pct=True).loc[0].where(grouped.count().eq(10))
8.49 ms ± 182 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
来自@Cimbali 的 Pandas 滑动窗口,快 105 倍:
%timeit scores_concat = pd.concat({n: df.shift(n).le(df) for n in range(10)}).groupby(level=1).sum() / 10
3.63 ms ± 136 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
来自@Cimbali 的求和移位版本,快 141 倍:
%timeit scores_sum = sum(df.shift(n).le(df) for n in range(10)).div(10)
2.71 ms ± 70.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
上面的 Numpy 滑动窗口解决方案。对于 1000 个元素,它比 Pandas 版本更快,约为 930x(并且可能使用更少的内存?),但更复杂。对于更大的数据集,它变得比 Pandas 版本慢。
%timeit data = df.to_numpy(); sw = sliding_window_view(data, 10, axis=0); scores_np = (sw <= sw[..., -1:]).sum(axis=2) / sw.shape[-1]; scores_np_df = pd.DataFrame(scores_np, columns=df.columns)
409 µs ± 4.43 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
最快的解决方案是移动坐标轴,对于 1000 行,比原始版本快 2800 倍,对于 100 万行,比 Pandas 求和版本快约 2 倍:
%timeit data = df.to_numpy(); sw = sliding_window_view(data, 10, axis=0).T; scores_np = (sw <= sw[-1:, ...]).sum(axis=0).T / sw.shape[0]; scores_np_df = pd.DataFrame(scores_np, columns=df.columns)
132 µs ± 750 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
关于python - 获得滚动百分位数排名的快速方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68831145/
假设我得到了两个整数 a, b 其中 a 是一个正整数并且小于 b 。我必须找到一种有效的算法,它会在 [a, b] 区间内给出 base2 位数(位数)的总和。例如,在区间 [0, 4] 中,数字之
到目前为止我已经尝试过不同的 autofilter但非选项似乎对我有用,我有许可证号列,其中应该只有 10 位数字,并且 autofilter我正在尝试查找少于或多于 10 位数字的条目, 我将该列转
谁能告诉我检查输入的数字是否为 3 位数字的正则表达式...它也不应该允许字母.... 最佳答案 3 个数字的正则表达式为 ^[0-9]{3}$ 或 ^\d{3}$ 关于javascript - 是否
我不知道这在 SQL Server 中是否可行,但我得问问它 ;-) 我在表 work 中有一个名为 duty 的列。 假设 Work.Duty 包含不同的数字,例如 (1, 2, 3, 20, 22
我正在运行一个我创建的java程序,它存储用户输入的数据。具体来说,有 4 个数组列表,分别是songName、songArtist、songYear 和songAlbum。我有一个“songYear
我不知道这在 SQL Server 中是否可行,但我得问问它 ;-) 我在表 work 中有一个名为 duty 的列。 假设 Work.Duty 包含不同的数字,例如 (1, 2, 3, 20, 22
给定一个 float ,我想使用半偶数舍入将结果四舍五入到小数点后四位,即四舍五入到下一个偶数的方法。例如,当我有以下代码片段时: #include #include int main(){
有没有一种方法可以在不使用小程序的情况下确定客户端计算机上的 jvm 位数?我确实看到了这个link但这决定了 jvm 版本而不是位数。提前致谢 最佳答案 您可以尝试确定浏览器位数 - 32 位 ja
我正在编写一个程序来计算给定数字的两个二进制表示之间的共同位数。我写的代码是: int common_bits(int a, int b) { static long binaryNo1,binary
如何使表格中的每个单元格的最小宽度为 3 位数字并且不会更大?现在我正在对 min-width 进行硬编码,但我不喜欢对值进行硬编码,因为将来我可能想更改字体。如果需要 Javascript 也没关系
我正在尝试匹配后跟一个空格或制表符和 5 个数字的单词。例如 some noise text off 12345 some noise text again. 另一个例子是: Some noise t
我在从 double 到 string 的转换时遇到问题。 我要转换: double value: 0.0772486324655191 string value: 0.077248632465519
我正在尝试实现一个使用 128 位 key 的密码。 key 计划的一部分是将 key 向右旋转 29 位,但我不确定该怎么做,因为 Java 中没有单一数据类型可以保存整个 key 。我将它存储在两
我正在尝试在 AVX2 中对 128 位数进行左旋转。由于没有直接的方法,我尝试使用左移和右移来完成我的任务。 这是我执行相同操作的代码片段。 l = 4; r = 4
我有一个 int,它的值类似于 1235 和 12890。我只想要这个 int 的前 2 位数字。我怎样才能提取它? 想了半天,想不出什么办法。 最佳答案 减少数字,直到只剩下两位数: while (
TL:DR 我想要紧跟“+”符号的任何行上的前两个数字的语法。 给定以下文本(来自熟悉的实用程序): power_meter-acpi-0 Adapter: ACPI interface power1
因此根据 cplusplus.com,当您通过以下方式将输出流的格式标志设置为科学记数法时 of.setf(ios::scientific) 您应该在指数中看到 3 位加号和一个符号。但是,我的输出似
这个问题在这里已经有了答案: How can I pad a value with leading zeros? (77 个答案) 关闭 9 年前。 如果小时数小于 10 小时,则小时数通常以个位数
我正在使用 moment.js使用根据距离/速度计算的日期时间。我也在使用 moment duration format plugin .当我将值传递给 moment.duration 然后对其进行格
我正在将一个应用程序从 .NET 移植到 Mono 运行时,并且在代码中的某个位置我可以看到一个 float 具有值 158136.422。我对 float 的理解是它是 7 位精度,那么这个数字如何
我是一名优秀的程序员,十分优秀!