python - 来自基于 3 列的 pandas DataFrame 的二维箱
问题描述
我正在尝试从基于 3 列的 pandas DataFrame 创建二维箱。这是我的 DataFrame 的一个片段:
Scatters N z Dist_first
---------------------------------------
0 0 0 0.096144 2.761508
1 1 0 -8.229910 17.403039
2 2 0 0.038125 21.466233
3 3 0 -2.050480 29.239867
4 4 0 -1.620470 NaN
5 5 0 -1.975930 NaN
6 6 0 -11.672200 NaN
7 7 0 -16.629000 26.554049
8 8 0 0.096002 NaN
9 9 0 0.176049 NaN
10 10 0 0.176005 NaN
11 11 0 0.215408 NaN
12 12 0 0.255889 NaN
13 13 0 0.301834 27.700308
14 14 0 -29.593600 9.155065
15 15 1 -2.582290 NaN
16 16 1 0.016441 2.220946
17 17 1 -17.329100 NaN
18 18 1 -5.442320 34.520919
19 19 1 0.001741 39.579189
对于我的结果,每个 Dist_first 都应该与组“N”中所有低于距离本身的索引的“z <= 0”进行分箱。“Scatters”是我的代码早期阶段的操作留下的索引副本,与此处无关。尽管如此,我还是开始使用它而不是下面示例中的索引。距离和 z 的 bin 分别以 10 m 和 0.1 m 为步长,我可以通过循环遍历数据帧组获得结果:
# create new column for maximal possible distances per group N
for j in range(N.groupby('N')['Dist_first'].count().max()):
N[j+1] = N.loc[N[N['Dist_first'].notna()].groupby('N')['Scatters'].nlargest(j+1).groupby('N').min()]['Dist_first']
# fill nans with zeros to allow
N[j+1] = N[j+1].fillna(0)
# make sure no value is repeated
if j+1 > 1:
N[j+1] = N[j+1]-N[list(np.arange(j)+1)].sum(axis=1)
# and set all values <= 0 to NaN
N[N[list(np.arange(N.groupby('N')['Dist_first'].count().max())+1)] <= 0] = np.nan
# backwards fill to make sure every distance gets all necessary depths
N[list(np.arange(N.groupby('N')['Dist_first'].count().max())+1)] = N.set_index('N').groupby('N').bfill().set_index('Scatters')[list(np.arange(N.groupby('N')['Dist_first'].count().max())+1)]
# bin the result(s)
for j in range(N.groupby('N')['Dist_first'].count().max()):
binned = N[N['z'] >= 0].groupby([pd.cut(N[N['z'] >= 0]['z'], bins_v, include_lowest=True), pd.cut(N[N['z'] >= 0][j+1], bins_h, include_lowest=True)])
binned = binned.size().unstack()
## rename
binned.index = N_v.index; binned.columns = N_h.index
## and sum up with earlier chunks
V = V+binned
这段代码工作得很好,我共享的一小段数据的结果如下所示:
Distance [m] 0.0 10.0 20.0 30.0 40.0
Depth [m]
----------------------------------------------------
0.0 1 1 1 4 2
0.1 1 2 2 4 0
0.2 0 3 0 3 0
0.3 0 2 0 2 0
0.4 0 0 0 0 0
但是,整个数据集非常大(每个数据集 > 300 mio 行),并且不能循环遍历所有行。因此,我正在寻找一些矢量化解决方案。
解决方案
我建议您在额外的列中计算 creiteria,然后使用 Pandas 标准分箱函数,如 qcut。它可以沿 2 个分箱维度单独应用。不是最优雅的,但绝对是矢量化的。
推荐阅读
- javascript - 检查数组中的所有值是否为真,然后返回一个真布尔语句(javascript)
- python - Leetcode Longest Common Prefix 运行时错误
- regex - 删除行的正则表达式
- android - Android - gRPC 客户端 - 从 Java 到 Kotlin
- javascript - CS50 PSet8 混搭 - 标记不显示在 Google 地图上
- php - 将值从一个数据库更新到另一个数据库 - 最快的方法
- php - 根据 Woocommerce 中的自定义价格更改产品价格
- ruby-on-rails - 创建自定义表单助手时是否需要 html_safe?
- android - 我可以使用 Google Actions 在我的应用中执行任务吗?
- wordpress - 如何配置 Apache 以使 Symfony4 路由在 WordPress 域的子目录中工作