io¶
Exchange formats of pharmacokinetic data.
Readers and writers for the table formats the field exchanges timecourses and
dosing protocols in. Every reader takes a pandas DataFrame (the caller reads
the csv, sas or xpt file) and returns a pkpdutils.timecourse.Timecourses
batch with one sample dimension, the times as given (a reader never shifts the
time axis), one route and the dosing protocol of every subject; analytes
reads several analytes of a table into one batch with a second sample
dimension:
- event records (
read_events,write_events): the one row per event format of NONMEM and Monolix, a row being a dose (EVID 1) or an observation (EVID 0). Repeated doses are given explicitly, asADDLadditional doses at the interdose intervalII, or as a steady state dose (SS 1); see Bauer (2019) and the Monolix data format documentation. - PKNCA tables (
read_pknca): the two table layout of the R packagePKNCA, the concentrations and the doses, joined on the subject and the grouping columns; see Denney et al. (2015). - CDISC ADNCA (
read_adnca): the analysis dataset of a non-compartmental analysis of the ADaM standard, one row per concentration record with the time since the first dose (AFRLT) and since the reference dose (ARRLT), see the CDISC ADaM ADNCA implementation guide (2021).
Every format is written back as well (write_events, write_pknca,
write_adnca), so a study round trips through any of them. The readers are
also reachable as the constructors Timecourses.from_events,
Timecourses.from_pknca and Timecourses.from_adnca, the writers as
Timecourses.to_events, to_pknca and to_adnca; the parameters of an
analysis are written as the CDISC PP domain by pkpdutils.cdisc.
import pandas as pd
from pkpdutils import Route, Timecourses
df = pd.read_csv("study.csv", na_values=".")
batch = Timecourses.from_events(
df, time_unit="hr", unit="ng/ml", dose_unit="mg", route=Route.ORAL
)
Columns are looked up case-insensitively, a column which is not in the table is
treated as absent (a missing required column raises). Compartment columns
(CMT, ADM) are not interpreted and modelled rates (RATE -1, RATE -2)
are not data: both are out of scope. A reader reads one route; a study of
several routes is read into one batch per route, which
Timecourses.from_timecourses combines into one multi-route batch.
The references of the formats are the "Data formats" section of
docs/references.md.
read_events
¶
read_events(
df,
*,
time_unit,
unit,
dose_unit,
route,
id_col="ID",
time_col="TIME",
dv_col="DV",
amt_col="AMT",
evid_col="EVID",
mdv_col="MDV",
rate_col="RATE",
tinf_col="TINF",
addl_col="ADDL",
ii_col="II",
ss_col="SS",
sd_col="SD",
se_col="SE",
n_col="N",
ss_doses=5,
keep_missing=True,
dim="individual",
analyte_col=None,
analytes=None,
analyte_dim=ANALYTE_DIM,
substance="substance",
covariates=None,
)
Read a batch from event records, the NONMEM and Monolix format.
A row of the table is one event of one subject: a dose when EVID is 1, an
observation when EVID is 0. An observation whose DV is missing or whose
MDV is 1 is a missing value: with keep_missing it keeps its time and is
read as NaN (the sampling grid of the table is the grid of the batch,
which is what a table of values below the limit of quantification needs),
without it the row is dropped. Rows with EVID 2 (other type event) or 3 (reset) are
dropped and counted in a warning; EVID 4 (reset and dose) raises, since a
reset starts a new period which the reader would silently merge into the
protocol of the subject (Bauer 2019). A row with EVID 1 and a value in
DV is a dose and an observation, which is how a table records a dose and
a sample at the same time.
Without an EVID column a row with AMT > 0 is a dose and nothing else,
the NM-TRAN semantics of a table without event identifiers; every other row
with a value in DV is an observation. A DV on such a dose row is
ignored and counted in a warning: a table which records a dose and a sample
in one row needs an EVID column.
The duration of an infusion is TINF (Monolix) when it is positive, else
AMT / RATE for a positive RATE; modelled rates (RATE -1, RATE -2)
are not data and raise. A dose record with ADDL and II stands for
ADDL further doses at the interdose interval, a record with SS == 1
for a dosing history of ss_doses preceding doses at the interdose
interval, and the batch is marked with attrs["steady_state_marker"];
ADDL > 0 or SS == 1 without a positive II is an incomplete table and
raises.
The Monolix column names AMOUNT, OBSERVATION, INFUSION DURATION,
INFUSION RATE, ADDITIONAL DOSES, INTERDOSE INTERVAL and STEADY
STATE are recognized as aliases (Monolix data format); the lookup of
every column is case-insensitive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
the event table, one row per dose or observation |
required |
time_unit
|
str
|
unit of the |
required |
unit
|
str
|
unit of the |
required |
dose_unit
|
str
|
unit of the |
required |
route
|
Route | str
|
route of the doses, a |
required |
id_col
|
str
|
name of the subject column |
'ID'
|
time_col
|
str
|
name of the time column |
'TIME'
|
dv_col
|
str
|
name of the observation column |
'DV'
|
amt_col
|
str
|
name of the dose amount column |
'AMT'
|
evid_col
|
str
|
name of the event identifier column |
'EVID'
|
mdv_col
|
str
|
name of the missing dependent value column |
'MDV'
|
rate_col
|
str
|
name of the infusion rate column |
'RATE'
|
tinf_col
|
str
|
name of the infusion duration column (Monolix) |
'TINF'
|
addl_col
|
str
|
name of the additional doses column |
'ADDL'
|
ii_col
|
str
|
name of the interdose interval column |
'II'
|
ss_col
|
str
|
name of the steady state column |
'SS'
|
sd_col
|
str
|
name of the standard deviation column of a group curve |
'SD'
|
se_col
|
str
|
name of the standard error column of a group curve |
'SE'
|
n_col
|
str
|
name of the column with the number of subjects of a group curve (constant within a subject) |
'N'
|
ss_doses
|
int
|
number of preceding doses a steady state record stands for |
5
|
keep_missing
|
bool
|
whether a missing observation ( |
True
|
dim
|
str
|
name of the sample dimension of the batch |
'individual'
|
analyte_col
|
str | None
|
name of the column which names the analyte of an
observation ( |
None
|
analytes
|
Sequence[str] | None
|
the analytes to read into one batch, which gives the sample
dimension |
None
|
analyte_dim
|
str
|
name of the sample dimension of |
ANALYTE_DIM
|
substance
|
str
|
name of the substance or effect |
'substance'
|
covariates
|
Sequence[str] | None
|
columns to keep as coordinates along |
None
|
Returns:
| Type | Description |
|---|---|
Timecourses
|
The batch, the subjects in the order of their first appearance and |
Timecourses
|
their |
Raises:
| Type | Description |
|---|---|
ValueError
|
if a required column ( |
write_events
¶
write_events(
timecourses,
*,
id_col="ID",
time_col="TIME",
dv_col="DV",
amt_col="AMT",
evid_col="EVID",
mdv_col="MDV",
rate_col="RATE",
sd_col="SD",
se_col="SE",
n_col="N",
)
Write a batch as event records, the inverse of read_events.
Every sample contributes one row per dose of its protocol (EVID 1,
MDV 1, no DV, the amount in AMT and, for an infusion, the rate
AMT / duration in RATE) and one row per observation (EVID 0,
AMT 0, RATE 0, MDV 0, or MDV 1 for a missing value). The rows of a
sample are sorted by time, the doses before the observations at the same
time; the samples keep the order of the batch. Repeated doses are written
out (no ADDL/II/SS), so the table is read back by read_events
without the expansion rules. The covariate coordinates along the sample
dimension become columns after the event columns.
A missing value is written as a row with MDV 1 and no DV, which
read_events reads back as a missing value at its time: the round trip
keeps the sampling grid, the observed points and the protocol.
A group curve carries its uncertainty in the columns sd_col, se_col and
n_col, written only when the batch has them: sd and se on the
observation rows, the number of subjects n on every row of the sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timecourses
|
Timecourses
|
the batch, with exactly one sample dimension |
required |
id_col
|
str
|
name of the subject column |
'ID'
|
time_col
|
str
|
name of the time column |
'TIME'
|
dv_col
|
str
|
name of the observation column |
'DV'
|
amt_col
|
str
|
name of the dose amount column |
'AMT'
|
evid_col
|
str
|
name of the event identifier column |
'EVID'
|
mdv_col
|
str
|
name of the missing dependent value column |
'MDV'
|
rate_col
|
str
|
name of the infusion rate column |
'RATE'
|
sd_col
|
str
|
name of the standard deviation column of a group curve |
'SD'
|
se_col
|
str
|
name of the standard error column of a group curve |
'SE'
|
n_col
|
str
|
name of the column with the number of subjects of a group curve |
'N'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
The event table with the subject, time, observation, amount, event |
DataFrame
|
identifier, missing value and rate columns, the uncertainty columns of |
DataFrame
|
a group curve and one column per covariate coordinate. |
Raises:
| Type | Description |
|---|---|
ValueError
|
if the batch does not have exactly one sample dimension. |
read_pknca
¶
read_pknca(
conc,
dose,
*,
time_unit,
unit,
dose_unit,
route,
conc_col="conc",
time_col="time",
dose_col="dose",
dose_time_col="time",
subject_col="subject",
duration_col="duration",
covariates=(),
dim="individual",
analyte_col=None,
analytes=None,
analyte_dim=ANALYTE_DIM,
substance="substance",
)
Read a batch from the two tables of the R package PKNCA.
The concentration table holds one row per subject and sampling time, the
dose table one row per subject and dose; both are joined on the subject
column (Denney et al. 2015). A subject without a row in the dose table gets
no protocol. PKNCA codes a value below the limit of quantification as 0
and a missing value as NA: both are kept as given (NaN for NA), the
lloq and blq options of the NCA handle them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conc
|
DataFrame
|
the concentration table |
required |
dose
|
DataFrame
|
the dose table |
required |
time_unit
|
str
|
unit of the time columns |
required |
unit
|
str
|
unit of the concentration column |
required |
dose_unit
|
str
|
unit of the dose column |
required |
route
|
Route | str
|
route of the doses, a |
required |
conc_col
|
str
|
name of the concentration column |
'conc'
|
time_col
|
str
|
name of the time column of |
'time'
|
dose_col
|
str
|
name of the dose amount column |
'dose'
|
dose_time_col
|
str
|
name of the time column of |
'time'
|
subject_col
|
str
|
name of the subject column of both tables |
'subject'
|
duration_col
|
str | None
|
name of the infusion duration column of |
'duration'
|
covariates
|
Sequence[str]
|
further columns of either table which are constant within a
subject; they become coordinates along |
()
|
dim
|
str
|
name of the sample dimension of the batch |
'individual'
|
analyte_col
|
str | None
|
name of the column which names the analyte of a row of
the concentration table (and of the dose table when it has one),
required with |
None
|
analytes
|
Sequence[str] | None
|
the analytes to read into one batch, which gives the sample
dimension |
None
|
analyte_dim
|
str
|
name of the sample dimension of |
ANALYTE_DIM
|
substance
|
str
|
name of the substance or effect |
'substance'
|
Returns:
| Type | Description |
|---|---|
Timecourses
|
The batch, the subjects in the order of their first appearance in |
Timecourses
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
if a required column is missing, if a covariate column is in neither table or is not constant within a subject, if the concentration table holds no subject, if a subject has fewer than two concentrations or duplicate times, or if the dose rows of a subject are not a valid protocol (a dose time which is not a number, a negative amount, a missing infusion duration), named with the subject. |
read_adnca
¶
read_adnca(
df,
*,
time_unit="hr",
unit=None,
dose_unit=None,
route=None,
subject_col="USUBJID",
analyte=None,
analytes=None,
param_col="PARAMCD",
value_col="AVAL",
value_unit_col="AVALU",
time_first_col="AFRLT",
time_ref_col="ARRLT",
dose_col="DOSEA",
dose_unit_col="DOSEU",
duration_col="ADUR",
nominal_time_col="NRRLT",
route_col="ROUTE",
dtype_col="DTYPE",
lloq_col="ALLOQ",
dim="individual",
analyte_dim=ANALYTE_DIM,
substance=None,
covariates=(),
)
Read a batch from a CDISC ADaM ADNCA (ADPC) dataset.
The dataset holds one row per concentration record of one analyte
(PARAMCD), with the time since the first dose (AFRLT) and the time
since the most recent dose (ARRLT) (CDISC ADNCA). The time of a record
is AFRLT, so the dose times of a subject are the distinct values of
AFRLT - ARRLT with the amount DOSEA of their records. Derived copies of
a record (DTYPE == "COPY", the pre-dose record duplicated into the
previous interval) are dropped.
The infusion duration is the ADUR of the records of a dose
(duration_col), which not every dataset carries: without the column an
infusion protocol cannot be read and a route of Route.IV_INFUSION raises
(Dosing requires a positive duration for every dose), and such a study is
read from the event records or from the PKNCA tables instead, which carry
the duration or the rate.
analytes reads several analytes of the dataset into one batch: every
analyte is read on its own and the batches are stacked along the sample
dimension analyte_dim, whose coordinate substance names the analyte of
every row (_stack_analytes). The analysis then follows the substance of
every sample and pkpdutils.nca.analytes.metabolite_ratio divides one by
the other.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
the ADNCA dataset |
required |
time_unit
|
str
|
unit of the time columns |
'hr'
|
unit
|
str | None
|
unit of the values, the first |
None
|
dose_unit
|
str | None
|
unit of the doses, the first |
None
|
route
|
Route | None
|
route of the doses, a |
None
|
subject_col
|
str
|
name of the subject column |
'USUBJID'
|
analyte
|
str | None
|
the analyte to read, the single analyte of the dataset by default |
None
|
analytes
|
Sequence[str] | None
|
the analytes to read into one batch, which gives the sample
dimension |
None
|
param_col
|
str
|
name of the parameter code column |
'PARAMCD'
|
value_col
|
str
|
name of the value column |
'AVAL'
|
value_unit_col
|
str
|
name of the unit column of the values |
'AVALU'
|
time_first_col
|
str
|
name of the column with the time since the first dose |
'AFRLT'
|
time_ref_col
|
str
|
name of the column with the time since the reference dose |
'ARRLT'
|
dose_col
|
str
|
name of the dose amount column |
'DOSEA'
|
dose_unit_col
|
str
|
name of the unit column of the doses |
'DOSEU'
|
duration_col
|
str | None
|
name of the infusion duration column, absent in most
datasets; the records of one dose must agree on it, |
'ADUR'
|
nominal_time_col
|
str | None
|
name of the nominal (planned) time column, absent in
many datasets; it becomes the variable |
'NRRLT'
|
route_col
|
str
|
name of the route column |
'ROUTE'
|
dtype_col
|
str
|
name of the derivation type column |
'DTYPE'
|
lloq_col
|
str
|
name of the column with the lower limit of quantification; it
becomes the coordinate |
'ALLOQ'
|
dim
|
str
|
name of the sample dimension of the batch |
'individual'
|
analyte_dim
|
str
|
name of the sample dimension of |
ANALYTE_DIM
|
substance
|
str | None
|
name of the substance, the analyte by default |
None
|
covariates
|
Sequence[str]
|
further columns which are constant within a subject; they
become coordinates along |
()
|
Returns:
| Type | Description |
|---|---|
Timecourses
|
The batch, the subjects in the order of their first appearance and |
Timecourses
|
their |
Raises:
| Type | Description |
|---|---|
ValueError
|
if a required column is missing, if both |
write_pknca
¶
write_pknca(
timecourses,
conc_path=None,
dose_path=None,
*,
conc_col="conc",
time_col="time",
dose_col="dose",
dose_time_col="time",
subject_col="subject",
duration_col="duration",
analyte_col="analyte",
)
Write a batch as the two tables of PKNCA, the inverse of read_pknca.
The concentration table holds one row per sample and observation (the
subject, the time and the value, NaN for a missing one) and the dose
table one row per sample and dose of its protocol (the subject, the dose
time, the amount and, for an infusion, its duration). The coordinates along
the subject dimension become further columns of the concentration table,
which read_pknca reads back as covariates; a batch of several analytes
(a substance coordinate along a second sample dimension) writes the
analyte of every row into analyte_col in both tables, which read_pknca
reads back as analytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timecourses
|
Timecourses
|
the batch, with one sample dimension or with an analyte dimension besides it |
required |
conc_path
|
str | Path | None
|
file to write the concentration table to, |
None
|
dose_path
|
str | Path | None
|
file to write the dose table to, |
None
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
conc_col |
str
|
name of the concentration column |
time_col |
str
|
name of the time column of the concentration table |
dose_col |
str
|
name of the dose amount column |
dose_time_col |
str
|
name of the time column of the dose table |
subject_col |
str
|
name of the subject column of both tables |
duration_col |
str
|
name of the infusion duration column, written only when the batch carries a duration |
analyte_col |
str
|
name of the analyte column, written only for a batch of several analytes |
Returns:
| Type | Description |
|---|---|
tuple[DataFrame, DataFrame]
|
The concentration table and the dose table. |
Raises:
| Type | Description |
|---|---|
ValueError
|
if the batch does not have the sample dimensions of a
table ( |
write_adnca
¶
write_adnca(
timecourses,
path=None,
*,
subject_col="USUBJID",
param_col="PARAMCD",
value_col="AVAL",
value_unit_col="AVALU",
time_first_col="AFRLT",
time_ref_col="ARRLT",
dose_col="DOSEA",
dose_unit_col="DOSEU",
duration_col="ADUR",
nominal_time_col="NRRLT",
route_col="ROUTE",
lloq_col="ALLOQ",
)
Write a batch as a CDISC ADaM ADNCA (ADPC) dataset, the inverse of read_adnca.
One row per sample and observation: AFRLT the time of the record,
ARRLT its time since the reference dose (the last dose at or before it,
the first dose for a record before it) and DOSEA the amount of that dose,
which is how read_adnca recovers the protocol of a subject. ADUR is the
duration of the reference dose of an infusion, ALLOQ the limit of
quantification of the subject and PARAMCD its analyte. The coordinates
along the subject dimension become further columns, which read_adnca
reads back as covariates. No row is a DTYPE == "COPY" duplicate.
A dose which is not followed by an observation is not the reference dose of any record and is therefore not in the dataset, which is a property of the format rather than of the writer: the protocol of a subject lives in the concentration records.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timecourses
|
Timecourses
|
the batch, with one sample dimension or with an analyte dimension besides it |
required |
path
|
str | Path | None
|
file to write to, |
None
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
subject_col |
str
|
name of the subject column |
param_col |
str
|
name of the analyte column |
value_col |
str
|
name of the value column |
value_unit_col |
str
|
name of the unit column of the values |
time_first_col |
str
|
name of the column with the time since the first dose |
time_ref_col |
str
|
name of the column with the time since the reference dose |
dose_col |
str
|
name of the dose amount column |
dose_unit_col |
str
|
name of the unit column of the doses |
duration_col |
str
|
name of the infusion duration column, written only when the batch carries a duration |
nominal_time_col |
str
|
name of the nominal (planned) time column, written
only when the batch carries the variable |
route_col |
str
|
name of the route column |
lloq_col |
str
|
name of the column with the limit of quantification, written only when the batch carries one |
Returns:
| Type | Description |
|---|---|
DataFrame
|
The dataset. |
Raises:
| Type | Description |
|---|---|
ValueError
|
if the batch does not have the sample dimensions of a
table ( |