В этом примере показано, как оценить специфичные для категории (такие как молодые от старых, мужские от женских), индивидуальные и общегосударственные параметры, используя данные профиля PK от нескольких индивидуумов.
Предположим, что у вас есть данные о концентрации лекарственного средства в плазме от 30 индивидуумов, и вы хотите оценить фармакокинетические параметры, а именно объемы центрального и периферического отделения, клиренс и межкомпартментарный клиренс. Предположим, что концентрация препарата в зависимости от временного профиля следует за биексоненциальным снижением , где - концентрация лекарственного средства в момент t, и и являются склонами для соответствующего экспоненциального падения.
Эти синтетические данные содержат временное течение концентраций в плазме 30 индивидуумов после болюсной дозы (100 мг), измеренной в разное время как для центрального, так и для периферического отделения. Он также содержит категориальные переменные, а именно Sex
и Age
.
clear
load('sd5_302RAgeSex.mat')
Преобразуйте набор данных в groupedData
объект, который является необходимым форматом данных для функции аппроксимации sbiofit
. A groupedData
объект также позволяет вам задать независимые имена переменных и групп (если они существуют). Установите модули ID
, Time
, CentralConc
, PeripheralConc
, Age
, и Sex
переменные. Модули являются необязательными и требуются только для UnitConversion
функция, которая автоматически преобразует совпадающие физические величины в одну последовательную единичную систему.
gData = groupedData(data); gData.Properties.VariableUnits = {'','hour','milligram/liter','milligram/liter','',''}; gData.Properties
ans = struct with fields:
Description: ''
UserData: []
DimensionNames: {'Row' 'Variables'}
VariableNames: {1x6 cell}
VariableDescriptions: {}
VariableUnits: {1x6 cell}
VariableContinuity: []
RowNames: {}
CustomProperties: [1x1 matlab.tabular.CustomProperties]
GroupVariableName: 'ID'
IndependentVariableName: 'Time'
The IndependentVariableName
и GroupVariableName
свойства были автоматически установлены на Time
и ID
переменные данных.
Отображение данных отклика для каждого индивидуума.
t = sbiotrellis(gData,'ID','Time',{'CentralConc','PeripheralConc'},... 'Marker','+','LineStyle','none'); % Resize the figure. t.hFig.Position(:) = [100 100 1280 800];
Используйте встроенную библиотеку PK для создания двухкамерной модели с инфузионным дозированием и устранением первого порядка, где скорость устранения зависит от зазора и объема центрального отделения. Используйте configset
объект для включения модуля.
pkmd = PKModelDesign; pkc1 = addCompartment(pkmd,'Central'); pkc1.DosingType = 'Bolus'; pkc1.EliminationType = 'linear-clearance'; pkc1.HasResponseVariable = true; pkc2 = addCompartment(pkmd,'Peripheral'); model = construct(pkmd); configset = getconfigset(model); configset.CompileOptions.UnitConversion = true;
Для получения дополнительной информации о создании компартментных моделей PK с помощью встроенной библиотеки SimBiology ®, смотрите, Создают Фармакокинетические модели.
Предположим, что каждый индивидуум получит болюсную дозу 100 мг во время = 0. Для получения дополнительной информации о настройке различных стратегий дозирования, смотрите Дозы в SimBiology Моделей.
dose = sbiodose('dose','TargetName','Drug_Central'); dose.StartTime = 0; dose.Amount = 100; dose.AmountUnits = 'milligram'; dose.TimeUnits = 'hour';
Данные содержат измеренную концентрацию плазмы в центральном и периферийном отсеках. Сопоставьте эти переменные с соответствующими компонентами модели, которые Drug_Central
и Drug_Peripheral
.
responseMap = {'Drug_Central = CentralConc','Drug_Peripheral = PeripheralConc'};
Укажите объемы центрального и периферийного отсеков Central
и Peripheral
, межкомпартментное разминирование Q12
, и зазор Cl_Central
как параметры для оценки. The estimatedInfo
позволяет вам опционально задать преобразования параметров, начальные значения и ограничения параметров. Начиная с обоих Central
и Peripheral
ограничены, чтобы быть положительным, задайте логарифмическое преобразование для каждого параметра.
paramsToEstimate = {'log(Central)', 'log(Peripheral)', 'Q12', 'Cl_Central'}; estimatedParam = estimatedInfo(paramsToEstimate,'InitialValue',[1 1 1 1]);
Оцените один набор параметров для каждого индивидуума путем установки 'Pooled'
аргумент пары "имя-значение" в false
.
unpooledFit = sbiofit(model,gData,responseMap,estimatedParam,dose,'Pooled',false);
Постройте график подгонки результатов по сравнению с исходными данными для каждого индивидуума (группы).
t = plot(unpooledFit);
% Resize the figure.
t.hFig.Position(:) = [100 100 1280 800];
Для неохлажденной подгонки, sbiofit
всегда возвращает по одному объекту результатов для каждого индивидуума.
Исследуйте неохлажденные оценки, чтобы увидеть, есть ли какие-либо параметры для категории, то есть, связаны ли некоторые параметры с одной или несколькими категориями. Если есть какие-либо зависимости категории, возможно, удастся уменьшить количество степеней свободы, оценив только значения этих параметров для категории.
Сначала извлеките идентификатор и значения категорий для каждого идентификатора
catParamValues = unique(gData(:,{'ID','Sex','Age'}));
Добавьте переменные в таблицу, содержащую оценку каждого параметра.
allParamValues = vertcat(unpooledFit.ParameterEstimates); catParamValues.Central = allParamValues.Estimate(strcmp(allParamValues.Name, 'Central')); catParamValues.Peripheral = allParamValues.Estimate(strcmp(allParamValues.Name, 'Peripheral')); catParamValues.Q12 = allParamValues.Estimate(strcmp(allParamValues.Name, 'Q12')); catParamValues.Cl_Central = allParamValues.Estimate(strcmp(allParamValues.Name, 'Cl_Central'));
Постройте графики оценок каждого параметра для каждой категории. gscatter
требует Statistics and Machine Learning Toolbox™. Если у вас его нет, используйте другие альтернативные функции построения графика, такие как plot
.
h = figure; ylabels = {'Central','Peripheral','Cl\_Central','Q12'}; plotNumber = 1; for i = 1:4 thisParam = estimatedParam(i).Name; % Plot for Sex category subplot(4,2,plotNumber); plotNumber = plotNumber + 1; gscatter(double(catParamValues.Sex), catParamValues.(thisParam), catParamValues.Sex); ax = gca; ax.XTick = []; ylabel(ylabels(i)); legend('Location','bestoutside') % Plot for Age category subplot(4,2,plotNumber); plotNumber = plotNumber + 1; gscatter(double(catParamValues.Age), catParamValues.(thisParam), catParamValues.Age); ax = gca; ax.XTick = []; ylabel(ylabels(i)); legend('Location','bestoutside') end % Resize the figure. h.Position(:) = [100 100 1280 800];
Исходя из графика, кажется, что молодые индивидуумы, как правило, имеют более высокие объемы центральных и периферийных отсеков (Central
, Peripheral
), чем старые индивидуумы (то есть объемы кажутся возрастными). У сложения мужчины, как правило, имеют более высокие скорости клиренса (Cl_Central
), чем самки, но противоположное для параметра Q12 (то есть клиренс и Q12 кажутся специфичными для пола).
Используйте 'CategoryVariableName'
свойство estimatedInfo
объект, чтобы указать, какую категорию использовать во время подбора кривой. Использование 'Sex'
как группа, подходящая для зазора Cl_Central
и Q12
параметры. Использование 'Age'
как группа, подходящая для Central
и Peripheral
параметры.
estimatedParam(1).CategoryVariableName = 'Age'; estimatedParam(2).CategoryVariableName = 'Age'; estimatedParam(3).CategoryVariableName = 'Sex'; estimatedParam(4).CategoryVariableName = 'Sex'; categoryFit = sbiofit(model,gData,responseMap,estimatedParam,dose)
categoryFit = OptimResults with properties: ExitFlag: 3 Output: [1x1 struct] GroupName: [] Beta: [8x5 table] ParameterEstimates: [120x6 table] J: [240x8x2 double] COVB: [8x8 double] CovarianceMatrix: [8x8 double] R: [240x2 double] MSE: 0.4362 SSE: 205.8690 Weights: [] LogLikelihood: -477.9195 AIC: 971.8390 BIC: 1.0052e+03 DFE: 472 DependentFiles: {1x3 cell} EstimatedParameterNames: {'Central' 'Peripheral' 'Q12' 'Cl_Central'} ErrorModelInfo: [1x3 table] EstimationFunction: 'lsqnonlin'
При подгонке по категориям (или группам) sbiofit
всегда возвращает один объект результатов, а не один для каждого уровня категории. Это потому, что как мужские, так и женские индивидуумы считаются частью одной и той же оптимизации с помощью одной и той же модели ошибки и параметров ошибки, аналогично для молодых и старых индивидуумов.
Постройте график предполагаемых результатов для конкретной категории.
t = plot(categoryFit);
% Resize the figure.
t.hFig.Position(:) = [100 100 1280 800];
Для Cl_Central
и Q12
параметры, все мужчины имели одинаковые оценки и аналогично для женщин. Для Central
и Peripheral
параметры, все молодые индивидуумы имели одинаковые оценки, и аналогично для старых индивидуумов.
Чтобы лучше сравнить результаты, подгоните модель ко всем данным, объединенным вместе, то есть оцените один набор параметров для всех индивидуумов путем установки 'Pooled'
аргумент пары "имя-значение" в true
. Предупреждающее сообщение указывает, что эта опция будет игнорировать любую информацию, относящуюся к категории (если она существует).
pooledFit = sbiofit(model,gData,responseMap,estimatedParam,dose,'Pooled',true);
Warning: CategoryVariableName property of the estimatedInfo object is ignored when using the 'Pooled' option.
Постройте график подгонки результатов по сравнению с исходными данными. Хотя для каждого индивидуума был сгенерирован отдельный график, данные подгонялись с использованием одного и того же набора параметров (то есть все индивидуумы имели одинаковую установленную линию).
t = plot(pooledFit);
% Resize the figure.
t.hFig.Position(:) = [100 100 1280 800];
Сравнение невязок CentralConc
и PeripheralConc
ответы для каждой подгонки.
t = gData.Time; allResid(:,:,1) = pooledFit.R; allResid(:,:,2) = categoryFit.R; allResid(:,:,3) = vertcat(unpooledFit.R); h = figure; responseList = {'CentralConc', 'PeripheralConc'}; for i = 1:2 subplot(2,1,i); oneResid = squeeze(allResid(:,i,:)); plot(t,oneResid,'o'); refline(0,0); % A reference line representing a zero residual title(sprintf('Residuals (%s)', responseList{i})); xlabel('Time'); ylabel('Residuals'); legend({'Pooled','Category-Specific','Unpooled'}); end % Resize the figure. h.Position(:) = [100 100 1280 800];
Как показано на графике, неохлажденная подгонка дала лучшее соответствие данным, так как она соответствует данным для каждого индивидуума. Это ожидалось, поскольку в нем использовалось наибольшее число степеней свободы. Подгонка по категории уменьшила количество степеней свободы, подгоняя данные к двум категориям (пол и возраст). В результате невязки были больше, чем неохлажденная подгонка, но все еще меньше, чем популяционная подгонка, которая оценивала всего один набор параметров для всех индивидуумов. Подгонка категории может быть хорошим компромиссом между неохлаждённым и объединённым подбором кривой при условии, что в ваших данных существует любая иерархическая модель.