Export Mesh Data to a DataFrame#

Convert a mesh’s point_data or cell_data to a pandas.DataFrame or pyarrow.Table for downstream analytics, export, or interactive exploration in IDEs like Positron’s Data Explorer, JupyterLab, or VS Code’s data viewer.

This example uses a classic CFD-style workflow: a scalar field and a vector field attached to a mesh, then filtered / aggregated / exported using pandas idioms.

import numpy as np
from pyvista import examples

Load a mesh and attach some data#

Use the hexbeam fixture mesh and attach a pressure scalar plus a velocity vector.

mesh = examples.load_hexbeam()
rng = np.random.default_rng(seed=0)
mesh.point_data['pressure'] = rng.normal(loc=100.0, scale=20.0, size=mesh.n_points)
mesh.point_data['velocity'] = rng.normal(size=(mesh.n_points, 3))

Convert to a pandas.DataFrame#

mesh.to_pandas() returns one row per point. Multi-component arrays are expanded to one column per component, named {array_name}_{i}.

sample_point_scalars VTKorigID pressure velocity_0 velocity_1 velocity_2
0 1 0 102.514604 -1.401520 0.502683 0.989713
1 2 1 97.357903 -0.164295 -1.074365 0.873042
2 4 2 112.808453 -1.280394 -0.713068 0.621018
3 6 3 102.098002 -2.250141 0.386370 -0.581641
4 8 4 89.286613 0.109280 -0.075702 0.202114


The DataFrame has n_points rows and one column per (expanded) array.

(99, 6)

Ad-hoc analytics#

Since we have a DataFrame, the full pandas API is available: filter, derive new columns, summarize.

velocity = df[['velocity_0', 'velocity_1', 'velocity_2']].to_numpy()
df['speed'] = np.linalg.norm(velocity, axis=1)
df[['pressure', 'speed']].describe()
pressure speed
count 99.000000 99.000000
mean 101.921452 1.612009
std 19.203438 0.670339
min 53.499385 0.241915
25% 87.435314 1.174939
50% 101.880246 1.521954
75% 114.773541 1.927140
max 140.047852 3.781354


Find the 5 highest-pressure points.

df.nlargest(5, 'pressure')[['pressure', 'speed']]
pressure speed
79 140.047852 1.633129
47 139.205166 1.591161
74 136.440227 1.271196
48 136.032697 1.838132
62 134.787358 1.471332


Cell-level export#

Pass association='cell' to export cell_data instead. The result has n_cells rows.

sample_cell_scalars quality
0 1 0.322921
1 2 0.990745
2 3 0.264695
3 4 0.830694
4 5 0.173114


Export to disk#

A DataFrame gives you one-liner access to every pandas I/O backend: Parquet, CSV, Feather, Excel, SQL, HDF5, and more. Commented out here to keep the gallery build clean.

# df.to_parquet('point_data.parquet')
# df.to_csv('point_data.csv', index=False)

Zero-copy Arrow interchange#

mesh, mesh.point_data, mesh.cell_data, and pyvista.Table all implement the Arrow PyCapsule interface, so any Arrow-aware library (polars, DuckDB, ibis, narwhals) can consume them without pyvista depending on those libraries. For example, with pyarrow:

import pyarrow as pa

arrow_table = pa.table(mesh)
arrow_table.schema
sample_point_scalars: int64
VTKorigID: int64
pressure: double
velocity_0: double
velocity_1: double
velocity_2: double

The mesh, mesh.point_data, and mesh.cell_data objects can also be opened directly in data-science IDE variable explorers (Positron, Jupyter, VS Code) after calling to_pandas(). The returned DataFrame renders as an interactive, sortable, filterable table.

Total running time of the script: (0 minutes 0.414 seconds)

Gallery generated by Sphinx-Gallery