python - 如何找到不同大小列表的中位数
问题描述
我有一个数字列表,我想将其分类到箱中并找到每个箱的中位数。如果这些 bin 都具有相同数量的数据点,那么使用 numpy 数组可以很容易地合理有效地执行此操作:
import numpy as np
indices=np.array([0,1,0,1,1,2,3,3,3,2,0,2])
length=np.max(indices)+1
data = np.arange(len(indices))
binned = np.array([data[indices == i] for i in range(length)])
然后分箱数据(在数组中binned
)
array([[ 0, 2, 10],
[ 1, 3, 4],
[ 5, 9, 11],
[ 6, 7, 8]])
每个 bin 的中位数为:
np.median(binned, axis=1)
结果:
array([2., 3., 9., 7.])
但是,如果列表是这样的,每个 bin 中有不同数量的点(或者某些 bin 中没有点),我不能创建一个 numpy 数组或使用 np.median 而是必须做繁重的工作一个for循环:
indices=np.array([0,1,1,1,3,1,1,0,0,0,3])
data = np.arange(len(indices))
分箱数据为
[data[indices == i] for i in range(length)]
[array([0, 7, 8, 9]),
array([1, 2, 3, 5, 6]),
array([], dtype=int64),
array([ 4, 10])]
但我不能取数组列表的中位数。相反,我可以做
[np.median(data[indices == i]) for i in range(length)]
并得到
[7.5, 3.0, nan, 7.0]
但是那个 for 循环非常慢。(我的真实数据中有几百万个数据点和数万或数十万个 bin。)
有没有办法避免严重依赖 for 循环(甚至完全摆脱 for 循环)?
解决方案
只需将两列放在pandas
DataFrame 中,您就可以通过按“索引”分组轻松计算中位数。让我们在实践中看看:
import numpy as np , pandas as pd
indices = [0,1,1,1,3,1,1,0,0,0,3]
data = np.arange(len(indices))
df = pd.DataFrame({"indices": indices, "data": data}) # Your DataFrame
df.head() # Take a look
indices data
0 0 0
1 1 1
2 1 2
3 1 3
4 3 4
medians = df.groupby("indices").median()# median for each value of `indices`
medians
data
indices
0 7.5
1 3.0
3 7.0
# Finding indices with no data point
desired_indices = pd.Series([0, 1, 10, -5, 2])
is_in_index = desired_indices.isin(medians.index)
has_no_data = desired_indices[~ is_in_index]
has_no_data
2 10
3 -5
4 2
dtype: int64
推荐阅读
- django - 将用户输入作为参数传递给下一个视图
- c++ - 如何在没有 CMake 的情况下使用 CGAL 绘图功能?
- r - qplot 不适用于 R 中的 grid.arrange 函数
- go - Go中切片的通用类型
- java - 错误:找不到符号导入静态 org.hamcrest.CoreMatchers.containsString;
- visual-studio - SSIS 2019 查找转换编辑器的 Visual Studio 2019 表单无法正确显示 - 行被挤压在一起
- ios - SwiftUI 致命错误:未找到“”类型的 ObservableObject 和 @EnvironmentObject 错误:可能作为此视图的祖先而丢失
- python - 从引号内的 JSON 字符串中删除 \r\n 以获得多行
- javascript - 谷歌地图功能未定义
- swift - SwiftUI:在 iPhone 8 上进行测试会削减部分视图,在某些组件上添加太多高度会导致白屏