python - 快速遍历列表、查找重复项和执行计算的方法
问题描述
我有两个列表,一个是相同大小的区域,一个是价格。
例如:面积 = [1500,2000,2000,1800,2000,1500,500] 价格 = [200,800,600,800,1000,750,200]
我需要返回每个独特区域的价格列表,不包括原始区域。
所以对于 1500,我需要返回的列表是:[750] 和 [200] 对于 2000,我需要返回的列表是 [600,1000]、[800,1000] 和 [800,600] 对于 1800 和 500 ,我需要返回的列表都是空列表[]。
然后,目标是确定一个值是否是受价格绝对值影响的异常值 - 平均值(不包括价格本身)小于 5 * 总体标准偏差(计算不包括价格本身)
import statistics
area = [1500,2000,2000,1800,2000,1500,500]
price = [200,800,600,800,1000,750,200]
outlier_idx = []
for idx, val in enumerate(area):
comp_idx = [i for i, x in enumerate(area) if x == val]
comp_idx.remove(idx)
comp_price = [price[i] for i in comp_idx]
if len(comp_price)>2:
sigma = statistics.stdev(comp_price)
p_m = statistics.mean(comp_price)
if abs(price[idx]-p_m) > 5 * sigma:
outlier_idx.append(idx)
area = [i for j, i in enumerate(area) if j not in outlier_idx]
price = [i for j, i in enumerate(price) if j not in outlier_idx]
问题是这种计算占用了大量时间,而且我正在处理可能非常大的数组。
我对如何提高计算效率感到困惑。
我愿意使用 numpy、pandas 或任何其他常用软件包。
此外,我在熊猫中尝试过这个问题:
df['p-p_m'] = ''
df['sigma'] = ''
df['outlier'] = False
for name, group in df.groupby('area'):
if len(group)>1:
idx = list(group.index)
for i in range(len(idx)):
tmp_idx = idx.copy()
tmp_idx.pop(i)
df['p-p_m'][idx[i]] = abs(group.price[idx[i]] - group.price[tmp_idx].mean())
df['sigma'][idx[i]] = group.price[tmp_idx].std(ddof=0)
if df['p-p_m'][idx[i]] > 3*df['sigma'][idx[i]]:
df['outlier'][idx[i]] = True
谢谢。
解决方案
这是一个结合了Numpy和Numba的解决方案。虽然正确,但我没有针对效率方面的替代方法对其进行测试,但 Numba 通常会显着加快需要循环数据的任务的速度。根据您的定义,我添加了一个异常值。
import numpy as np
from numba import jit
# data input
price = np.array([200,800,600,800,1000,750,200, 2000])
area = np.array([1500,2000,2000,1800,2000,1500,500, 1500])
@jit(nopython=True)
def outliers(price, area):
is_outlier = np.full(len(price), False)
for this_area in set(area):
indexes = area == this_area
these_prices = price[indexes]
for this_price in set(these_prices):
arr2 = these_prices[these_prices != this_price]
if arr2.size > 1:
std = arr2.std()
mean = arr2.mean()
indices = (this_price == price) & (this_area == area)
is_outlier[indices] = np.abs(mean - this_price) > 5 * std
return is_outlier
> outliers(price, area)
> array([False, False, False, False, False, False, False, True])
如果每个区域有多个相同的价格水平,代码应该很快,因为它们会同时更新。
我希望这有帮助。
推荐阅读
- loops - 如何使用嵌套在 for 循环中的 While 循环在 R 中创建向量?
- php - 使用 PHP 对数组中的匹配对进行分组
- json - 使用 jq,是否可以返回相同的 json 对象,但只能在多个级别上使用选定的字段/键?
- r - 在 data.table 连接中选择我从哪一列接收结果 - R
- python - 如何根据单个列上的多个条件获取 ID 计数?
- php - 为什么 php 代码不过滤 MySQL 数据库中的现有记录
- java - 使用 ContentCachingResponseWrapper 模拟测试过滤器
- prometheus - 在普罗米修斯中查找重复标签
- reactjs - 如何键入一个将返回 AxiosResponse 的函数作为其参数之一的通用组件?
- python - 如何在 sklearn 中使用 Lasso-GridSearchCV 的 BIC 和 AIC 分数?