# Notebook

An interactive dataset viewer that runs entirely in your browser through WebAssembly (marimo + Pyodide) -- no install, no server. Pick any of the 161 datasets, choose the columns and the number of rows, and browse the result.

The viewer installs the `pharmadata` package wheel via `micropip` and loads datasets through its public API -- the same data the package ships.


<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld2JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJzaXplLTIwIGFuaW1hdGUtc3BpbiB0ZXh0LXByaW1hcnkiPgogICAgICA8cGF0aCBkPSJNMjEgMTJhOSA5IDAgMSAxLTYuMjE5LTguNTYiIC8+CiAgICA8L3N2Zz4=" class="size-20 animate-spin text-primary" />


Initializing...


%23%20Aliases%20are%20underscore-private%3A%20the%20install%20cell%20owns%20the%20public%20%60mo%60%0A%23%20and%20%60sys%60%20names%2C%20and%20this%20cell%20must%20run%20before%20that%20one.%0Aimport%20marimo%20as%20_mo%0A%0A%23%20Loading-banner%20state%3A%20False%20while%20the%20WASM%20kernel%20is%20still%20installing%0A%23%20packages%3B%20the%20install%20cell%20below%20flips%20it%20to%20True%2C%20which%20re-runs%20the%0A%23%20banner%20cell%20and%20clears%20the%20message.%0Apackages_ready%2C%20set_packages_ready%20%3D%20_mo.state(False) import%20marimo%20as%20_mo%0Aimport%20sys%20as%20_sys%0A%0A%23%20WASM%20pages%20download%20numpy%2C%20pandas%2C%20pyarrow%2C%20polars%20and%20the%20pharmadata%0A%23%20wheel%20before%20the%20viewer%20is%20usable.%20This%20cell%20does%20not%20depend%20on%20the%0A%23%20install%20cell%2C%20so%20it%20runs%20first%20and%20shows%20what%20is%20happening%3B%20the%20state%0A%23%20flip%20clears%20the%20banner%20once%20the%20install%20cell%20finishes.%0Abanner%20%3D%20(%0A%20%20%20%20_mo.md(%0A%20%20%20%20%20%20%20%20%22\*\*Loading%20numpy%2C%20pandas%2C%20pyarrow%2C%20polars\*\*%20%E2%80%94%20first%20load%20%22%0A%20%20%20%20%20%20%20%20%22downloads%20~10%20MB%20of%20packages%3B%20the%20controls%20and%20table%20below%20%22%0A%20%20%20%20%20%20%20%20%22become%20interactive%20once%20the%20kernel%20finishes.%22%0A%20%20%20%20)%0A%20%20%20%20if%20_sys.platform%20%3D%3D%20%22emscripten%22%20and%20not%20packages_ready()%0A%20%20%20%20else%20None%0A)%0Abanner import%20marimo%20as%20mo%0A%0A%23%20In%20WASM%20the%20package%20is%20not%20pre-installed%3B%20fetch%20the%20wheel%20served%0A%23%20alongside%20this%20notebook%20and%20install%20it%20with%20micropip.%0Aimport%20sys%0A%0Aif%20sys.platform%20%3D%3D%20%22emscripten%22%3A%0A%20%20%20%20import%20micropip%20%20%23%20type%3A%20ignore%5Bimport-not-found%5D%0A%20%20%20%20from%20js%20import%20location%20as%20js_location%20%20%23%20type%3A%20ignore%5Bimport-not-found%5D%0A%20%20%20%20from%20pyodide.http%20import%20pyfetch%20%20%23%20type%3A%20ignore%5Bimport-not-found%5D%0A%0A%20%20%20%20%23%20Live%20status%20while%20the%20browser%20downloads%20the%20packages.%0A%20%20%20%20with%20mo.status.spinner(%0A%20%20%20%20%20%20%20%20title%3D%22Loading%20packages%22%2C%0A%20%20%20%20%20%20%20%20subtitle%3D%22numpy%2C%20pandas%2C%20pyarrow%2C%20polars%20(~10%20MB)%22%2C%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20%23%20Dependencies%20with%20C%20extensions%20are%20provided%20as%20Pyodide%20packages%3B%0A%20%20%20%20%20%20%20%20%23%20tzdata%20is%20pure-python.%20Install%20them%20before%20unpacking%20the%20wheel.%0A%20%20%20%20%20%20%20%20await%20micropip.install(%5B%22polars%22%2C%20%22pyarrow%22%2C%20%22tzdata%22%5D)%20%20%23%20noqa%3A%20F704%0A%0A%20%20%20%20%20%20%20%20%23%20marimo's%20html-wasm%20export%20runs%20Pyodide%20inside%20a%20blob%3A%20Web%0A%20%20%20%20%20%20%20%20%23%20Worker%2C%20so%20location.href%20is%20a%20blob%20URL%20and%20location.origin%20is%0A%20%20%20%20%20%20%20%20%23%20all%20we%20know.%20The%20wheel%20lives%20at%0A%20%20%20%20%20%20%20%20%23%20%3Csite-root%3E%2Fnotebooks%2Fpharmadata-0.0.0-py3-none-any.whl%3B%20try%0A%20%20%20%20%20%20%20%20%23%20the%20likely%20site-root%20paths%20against%20the%20worker's%20origin%20and%20keep%0A%20%20%20%20%20%20%20%20%23%20the%20first%20that%20serves%20the%20wheel.%0A%20%20%20%20%20%20%20%20origin%20%3D%20str(js_location.origin)%0A%20%20%20%20%20%20%20%20wheel_name%20%3D%20%22pharmadata-0.0.0-py3-none-any.whl%22%0A%20%20%20%20%20%20%20%20candidates%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%7Borigin%7D%2Fpharmadata%2Fnotebooks%2F%7Bwheel_name%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%7Borigin%7D%2Fnotebooks%2F%7Bwheel_name%7D%22%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20resp%20%3D%20None%0A%20%20%20%20%20%20%20%20for%20candidate%20in%20candidates%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20resp%20%3D%20await%20pyfetch(candidate)%20%20%23%20noqa%3A%20F704%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20resp.status%20%3D%3D%20200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20if%20resp%20is%20None%20or%20resp.status%20!%3D%20200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20RuntimeError(f%22pharmadata%20wheel%20not%20found%20(tried%20%7Bcandidates%7D)%22)%0A%0A%20%20%20%20%20%20%20%20%23%20unpack_archive()%20unzips%20the%20wheel%20directly%20from%20the%20JS%0A%20%20%20%20%20%20%20%20%23%20ArrayBuffer%2C%20bypassing%20Python%20bytes%20conversion%20which%20corrupts%0A%20%20%20%20%20%20%20%20%23%20large%20(%3Efew%20MB)%20buffers.%20Then%20add%20the%20unpacked%20dir%20to%20sys.path%0A%20%20%20%20%20%20%20%20%23%20so%20imports%20resolve.%0A%20%20%20%20%20%20%20%20import%20sys%20as%20_sys%0A%0A%20%20%20%20%20%20%20%20pkg_dir%20%3D%20%22%2Ftmp%2Fpharmadata_pkg%22%0A%20%20%20%20%20%20%20%20await%20resp.unpack_archive(extract_dir%3Dpkg_dir)%20%20%23%20noqa%3A%20F704%0A%20%20%20%20%20%20%20%20_sys.path.insert(0%2C%20pkg_dir)%0A%20%20%20%20set_packages_ready(True)%0Afrom%20pharmadata%20import%20cdiscpilotadam%2C%20cdiscpilotsdtm%2C%20pharmaverseadam%2C%20pharmaversesdtm%0A%0ACOLLECTIONS%20%3D%20%5Bpharmaverseadam%2C%20pharmaversesdtm%2C%20cdiscpilotadam%2C%20cdiscpilotsdtm%5D


%23%20Build%20%22%3Ccollection%3E\_%3Cdataset%3E%22%20keys%20for%20every%20dataset%2C%20matching%20the%0A%23%20naming%20the%20shipped%20parquet%20files%20use.%0Aentries%3A%20list%5Btuple%5Bstr%2C%20object%2C%20str%5D%5D%20%3D%20%5B%5D%0Afor%20_coll%20in%20COLLECTIONS%3A%0A%20%20%20%20_cname%20%3D%20_coll.\_\_name\_\_.rsplit(%22.%22%2C%201)%5B-1%5D%0A%20%20%20%20for%20_name%20in%20_coll.list_datasets()%3A%0A%20%20%20%20%20%20%20%20entries.append((f%22%7B_cname%7D\_%7B_name%7D%22%2C%20_coll%2C%20_name))%0Aoptions%20%3D%20%7Bkey.replace(%22\_%22%2C%20%22%20%2F%20%22%2C%201)%3A%20key%20for%20key%2C%20\_%2C%20\_%20in%20entries%7D%0Alookup%20%3D%20%7Bkey%3A%20(coll%2C%20name)%20for%20key%2C%20coll%2C%20name%20in%20entries%7D%0Adataset%20%3D%20mo.ui.dropdown(options%3Doptions%2C%20value%3Dnext(iter(options))%2C%20label%3D%22Dataset%22)%0Anrows%20%3D%20mo.ui.slider(5%2C%20100%2C%20value%3D10%2C%20step%3D5%2C%20label%3D%22Rows%22)%0Amo.hstack(%5Bdataset%2C%20nrows%5D%2C%20justify%3D%22start%22) import%20polars%20as%20pl%0A%0Aselected%20%3D%20dataset.value%20if%20hasattr(dataset%2C%20%22value%22)%20else%20dataset%0Acollection%2C%20name%20%3D%20lookup%5Bselected%5D%0Adf%20%3D%20pl.DataFrame(getattr(collection%2C%20name))%0Acolumns%20%3D%20mo.ui.multiselect(%0A%20%20%20%20options%3Ddf.columns%2C%0A%20%20%20%20value%3Ddf.columns%5B%3A%20min(10%2C%20len(df.columns))%5D%2C%0A%20%20%20%20label%3D%22Columns%22%2C%0A)%0Acolumns sel%20%3D%20dataset.value%20if%20hasattr(dataset%2C%20%22value%22)%20else%20dataset%0An%20%3D%20nrows.value%20if%20hasattr(nrows%2C%20%22value%22)%20else%20nrows%0Acols%20%3D%20columns.value%20if%20hasattr(columns%2C%20%22value%22)%20else%20columns%0Acols%20%3D%20list(cols)%20if%20cols%20else%20%5B%5D%0Aview%20%3D%20df.select(cols).head(n)%0A%23%20The%20table's%20built-in%20Export%20works%20in%20WASM%3A%20download_as%20runs%20in%20the%0A%23%20Pyodide%20worker%20and%2C%20with%20no%20virtual-file%20server%20there%2C%20embeds%20the%0A%23%20payload%20as%20a%20data%3A%20URL%20that%20the%20frontend%20hands%20to%20an%20anchor%20click.%0A%23%20CSV%2FTSV%2FJSON%2FParquet%20downloads%20and%20clipboard%20copies%20all%20work%20on%20the%0A%23%20static%20site%3B%20show_search%3DFalse%20just%20keeps%20the%20toolbar%20lean.%0Amo.ui.table(view%2C%20selection%3DNone%2C%20label%3Dsel%2C%20show_search%3DFalse)


![](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld2JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxyZWN0IHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgeD0iOCIgeT0iOCIgcng9IjIiIHJ5PSIyIiAvPjxwYXRoIGQ9Ik00IDE2Yy0xLjEgMC0yLS45LTItMlY0YzAtMS4xLjktMiAyLTJoMTBjMS4xIDAgMiAuOSAyIDIiIC8+PC9zdmc+) Copy Notebook

Run locally: `marimo edit dataset_viewer.py`
