Tenho dados de pontos 3D irregulares que se parecem com isto:
import numpy as np
import pandas as pd
xx, yy = np.meshgrid(
np.linspace(-50, 50, 101),
np.linspace(-50, 50, 101),
)
rng = np.random.default_rng(12345)
xx += rng.normal(size=101 * 101).reshape((101, 101))
yy += rng.normal(size=101 * 101).reshape((101, 101))
df3d = pd.DataFrame({
"X": np.broadcast_to(xx, (11, 101, 101)).T.flatten(),
"Y": np.broadcast_to(yy, (11, 101, 101)).T.flatten(),
"Z": np.broadcast_to(np.arange(11, dtype=float), (101, 101, 11)).flatten(),
})
df3d
X Y Z
0 -51.423825 -51.287428 0.0
1 -51.423825 -51.287428 1.0
2 -51.423825 -51.287428 2.0
3 -51.423825 -51.287428 3.0
4 -51.423825 -51.287428 4.0
... ... ...
112206 51.593733 50.465087 6.0
112207 51.593733 50.465087 7.0
112208 51.593733 50.465087 8.0
112209 51.593733 50.465087 9.0
112210 51.593733 50.465087 10.0
[112211 rows x 3 columns]
Com minha análise, preciso agrupá-los em locais 2D com 1 ou mais medidas Z (nem sempre são 11 para meus dados do mundo real):
gb2d = df3d.groupby(["X", "Y"])
df2d = gb2d["Z"].count().to_frame("count")
df2d["Zmin"] = gb2d["Z"].min()
df2d["Zmax"] = gb2d["Z"].max()
df2d.reset_index()
X Y count Zmin Zmax
0 -51.995857 -49.653017 11 0.0 10.0
1 -51.939229 24.073164 11 0.0 10.0
2 -51.740996 -5.415639 11 0.0 10.0
3 -51.645503 21.830189 11 0.0 10.0
4 -51.639759 -42.850923 11 0.0 10.0
... ... ... ... ...
10196 51.593733 50.465087 11 0.0 10.0
10197 51.905789 37.538099 11 0.0 10.0
10198 51.989935 -32.464752 11 0.0 10.0
10199 52.530599 -40.110744 11 0.0 10.0
10200 52.902015 -6.111877 11 0.0 10.0
[10201 rows x 5 columns]
Pergunta: Como eu atribuiria o índice inteiro de df2d (mostrado acima) de volta ao quadro pai df3d?
Minha melhor tentativa funciona, mas não escala bem com frames maiores. Por exemplo:
idx2d = pd.Series(np.arange(len(df2d)), index=df2d.index)
df3d["idx2d"] = idx2d.loc[df3d[["X", "Y"]].to_records(index=False).tolist()].values
funciona para esse tamanho de amostra, mas ocupa mais do que meus 32 GB de RAM com meus dados do mundo real de 24 milhões de pontos. Qual é uma maneira melhor que não consuma toda a minha RAM?