This tutorial illustrates calculation of intraindividual variability metrics. Specifically, this tutorial demonstrates calculation of a few univariate metrics, a few bivariate metrics, and a few multivariate metrics - as well as how these metrics are related to other individual differences.
A. Univariate IIV Metrics
B. Bivariate IIV Metrics
C. Multivariate IIV Metrics
D. Selected Readings
Loading Libraries
Loading libraries used in this script.
library(psych) # for describing the data
library(plyr) #for data manipulation
library(ggplot2) # for data visualization
library(entropy) #for entropy calculation
library(nFactors) #factor analysis
Loading Data
Our example makes use of the person-level and interaction-level (EMA-type) AMIB data files. We make use of person-level personality variables and a small set of interaction-level variables.
Loading person-level file and subsetting to variables of interest
#set filepath for data file
filepath <- "https://quantdev.ssri.psu.edu/sites/qdev/files/AMIBshare_persons_2019_0501.csv"
#read in the .csv file using the url() function
AMIB_persons <- read.csv(file=url(filepath),header=TRUE)
#subsetting to variables of interest
AMIB_persons <- AMIB_persons[ ,c("id","bfi_o","bfi_c","bfi_e","bfi_a","bfi_n")]
Loading day-level file (T = 21) and subsetting to variables of interest.
#set filepath for data file
filepath <- "https://quantdev.ssri.psu.edu/sites/qdev/files/AMIBshare_phase2_daily_2019_0501.csv"
#read in the .csv file using the url() function
AMIB_daily <- read.csv(file=url(filepath),header=TRUE)
There are several types of univariate IIV metrics that differ based on the type of data (continuous, binary, count), and conceptual meanings. For example, the iMean, iSD, iSkew, and iKurtosis are the first four distribution moments, utilize continuous data, and are unstructured with respect to time. iMSSD and iPAC also utilize continuous data, but do acount for time dependencies in the data. iEntropy and iTurbulence pertain to categorical data.
We illustrate just a few. The general principle is to use the functions in the plyr
package to split the data by “id” and summarize each person’s data using a specifci fucntion (e.g., mean, sd). We will use this same approach when preparing data in later analyses.
Calculating univariate IIV metrics.
istats_univariate <- ddply(AMIB_daily, "id", summarize,
icount_posaff = sum(!is.na(posaff)), #count of observations
imean_posaff = mean(posaff, na.rm=TRUE), #imean (continuous)
isd_posaff = sd(posaff, na.rm=TRUE), #isd (continuous)
iskew_posaff = skew(posaff, na.rm=TRUE), #iskew (continuous)
ikurt_posaff = kurtosi(posaff, na.rm=TRUE), # ikurtosis (continuous)
ientropy_stress= entropy(table(stress,
useNA="no"))) #(categorical)
Look at univariate IIV metrics data
round(head(istats_univariate),2)
## id icount_posaff imean_posaff isd_posaff iskew_posaff ikurt_posaff
## 1 203 22 4.42 0.84 -0.70 0.13
## 2 204 22 3.10 1.17 -0.58 -1.19
## 3 205 22 4.32 0.68 -0.73 -0.53
## 4 208 22 3.92 0.67 0.11 -0.86
## 5 211 22 2.81 0.85 0.70 -0.15
## 6 214 15 4.16 1.01 -0.46 -0.82
## ientropy_stress
## 1 1.00
## 2 1.49
## 3 1.67
## 4 1.02
## 5 1.36
## 6 1.90
Describe the bivariate IIV metrics
describe(istats_univariate[-1])
## vars n mean sd median trimmed mad min max range
## icount_posaff 1 30 20.90 2.58 22.00 21.58 0.00 14.00 22.00 8.00
## imean_posaff 2 30 3.78 0.71 3.91 3.76 0.56 2.61 5.62 3.01
## isd_posaff 3 30 0.88 0.26 0.87 0.87 0.26 0.32 1.52 1.20
## iskew_posaff 4 30 -0.15 0.46 -0.24 -0.19 0.46 -0.74 0.97 1.71
## ikurt_posaff 5 30 -0.79 0.50 -0.88 -0.84 0.47 -1.43 0.58 2.01
## ientropy_stress 6 30 1.47 0.28 1.50 1.48 0.28 0.84 1.90 1.06
## skew kurtosis se
## icount_posaff -2.02 2.28 0.47
## imean_posaff 0.29 -0.17 0.13
## isd_posaff 0.17 -0.19 0.05
## iskew_posaff 0.69 -0.45 0.08
## ikurt_posaff 0.94 0.01 0.09
## ientropy_stress -0.39 -0.77 0.05
Examine correlations
round(cor(istats_univariate[ ,-1], use="pairwise.complete.obs"),2)
## icount_posaff imean_posaff isd_posaff iskew_posaff
## icount_posaff 1.00 0.08 -0.32 0.16
## imean_posaff 0.08 1.00 -0.45 -0.38
## isd_posaff -0.32 -0.45 1.00 0.21
## iskew_posaff 0.16 -0.38 0.21 1.00
## ikurt_posaff 0.24 0.14 -0.07 0.29
## ientropy_stress -0.06 -0.24 0.29 -0.21
## ikurt_posaff ientropy_stress
## icount_posaff 0.24 -0.06
## imean_posaff 0.14 -0.24
## isd_posaff -0.07 0.29
## iskew_posaff 0.29 -0.21
## ikurt_posaff 1.00 -0.11
## ientropy_stress -0.11 1.00
Merge the univariate IIV metrics with other person-level data.
AMIB_univariate <- merge(istats_univariate, AMIB_persons, by="id")
Examine relation between positive affect variability and neuroticism.
Look at association between isd_posaff
and bfi_n
:
#pdf("UnivariateIIV.pdf",height=5.75, width=9)
ggplot(data=AMIB_univariate, aes(x=bfi_n, y=isd_posaff)) +
geom_point(colour="gray40") +
geom_smooth(aes(group=1), method=lm, se=TRUE, fullrange=TRUE, lty=1, size=2, color="#9A23DE") +
scale_y_continuous(breaks=c(0.4, 0.8, 1.2, 1.6), limits=c(0.32,1.6)) +
xlab("Neuroticism") + ylab("Positive Affect Variability") +
theme_classic() +
theme(axis.title=element_text(size=16),
axis.text=element_text(size=12),
plot.title=element_text(size=16, hjust=.5, face="bold")) +
ggtitle("Between-Person Association Univariate IIV")
## Warning: Removed 1 rows containing non-finite values (stat_smooth).
## Warning: Removed 1 rows containing missing values (geom_point).
#dev.off()
And the formal model test (cross-sectional regression).
reg_univariate <- lm(isd_posaff ~ bfi_n,
data=AMIB_univariate,
na.action = na.exclude)
summary(reg_univariate)
##
## Call:
## lm(formula = isd_posaff ~ bfi_n, data = AMIB_univariate, na.action = na.exclude)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.49597 -0.14662 -0.00169 0.18189 0.49217
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.59383 0.15329 3.874 0.000589 ***
## bfi_n 0.08654 0.04499 1.923 0.064654 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.252 on 28 degrees of freedom
## Multiple R-squared: 0.1167, Adjusted R-squared: 0.08516
## F-statistic: 3.699 on 1 and 28 DF, p-value: 0.06465
There are are also several types of bivariate IIV metrics, including the iCorr, iCov, iPulse, iSpin, and iEntropy. The slope parameter from a within-person regression can, along with the iCorr and iCov also be considered a measure of intraindividual covariation.
We illustrate just a few of these. Again, the general principle is to use the functions in the plyr
package to split the data by “id” and summarize each person’s data using a specific fucntion (e.g., cor, lm).
Calculate intraindiviudal correlation (iCor) and intraindividual covariance (iCov) and intraindividual regression (iReg):
istats_bivariate <- ddply(AMIB_daily, "id", summarize,
icor_affect = cor(x=posaff,y=negaff,
use="pairwise.complete.obs", method="pearson"),
icov_affect = cov(x=posaff,y=negaff,
use="pairwise.complete.obs", method="pearson"),
ireg_affect = coef(lm(posaff ~ negaff, na.action=na.exclude))[2])
Look at bivariate IIV metrics data
round(head(istats_bivariate),2)
## id icor_affect icov_affect ireg_affect
## 1 203 -0.63 -0.29 -0.98
## 2 204 -0.77 -1.18 -0.70
## 3 205 -0.44 -0.17 -0.53
## 4 208 -0.35 -0.06 -0.88
## 5 211 -0.08 -0.02 -0.17
## 6 214 -0.85 -0.83 -0.89
Describe the bivariate IIV metrics
describe(istats_bivariate[ ,-1])
## vars n mean sd median trimmed mad min max range skew
## icor_affect 1 30 -0.49 0.27 -0.54 -0.50 0.32 -0.90 0.01 0.91 0.30
## icov_affect 2 30 -0.39 0.41 -0.25 -0.32 0.31 -1.73 0.01 1.74 -1.61
## ireg_affect 3 30 -0.58 0.35 -0.62 -0.58 0.43 -1.21 0.03 1.24 0.03
## kurtosis se
## icor_affect -1.24 0.05
## icov_affect 2.28 0.07
## ireg_affect -1.20 0.06
Correlations among the bivariate IIV metrics
round(cor(istats_bivariate[ ,-1], use="pairwise.complete.obs"),2)
## icor_affect icov_affect ireg_affect
## icor_affect 1.00 0.73 0.84
## icov_affect 0.73 1.00 0.51
## ireg_affect 0.84 0.51 1.00
Note the overlap between the iCor, iCov, and iReg metrics. This will be relevant when extending the iReg into the multilevel modeling framework - to examine between-person differences in intraindividual covariation.
Merge the bivariate IIV metrics with other person-level data.
AMIB_bivariate <- merge(istats_bivariate, AMIB_persons, by="id")
Examine relation between Affect Bipolarity and neuroticism.
Look at association between isd_posaff
and bfi_e
:
#pdf("BivariateIIV.pdf",height=3, width=9)
ggplot(data=AMIB_bivariate, aes(x=bfi_n, y=icor_affect)) +
geom_point(colour="gray40") +
geom_smooth(aes(group=1), method=lm, se=TRUE, fullrange=TRUE, lty=1, size=2, color="#9A23DE") +
xlab("Neuroticism") + ylab("Affect Bipolarity") +
theme_classic() +
theme(axis.title=element_text(size=16),
axis.text=element_text(size=12),
plot.title=element_text(size=16, hjust=.5, face="bold")) +
ggtitle("Between-Person Association Bivariate IIV")
#dev.off()
Fit model with the neuroticism predicting the individual slope score for the association between positive and negative affect.
reg_bivariate <- lm(icor_affect ~ bfi_n,
data=AMIB_bivariate,
na.action = na.exclude)
summary(reg_bivariate)
##
## Call:
## lm(formula = icor_affect ~ bfi_n, data = AMIB_bivariate, na.action = na.exclude)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.42499 -0.20524 -0.05017 0.24066 0.51684
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.42619 0.16959 -2.513 0.018 *
## bfi_n -0.01979 0.04978 -0.398 0.694
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2788 on 28 degrees of freedom
## Multiple R-squared: 0.005616, Adjusted R-squared: -0.0299
## F-statistic: 0.1581 on 1 and 28 DF, p-value: 0.6939
Calculation of intraindividual variability metrics can be extended to multivariate time-series. Continuous measures can be summarized as a correlation/covariance matrix (and vector of means) - which in turn is summarized using metrics such as the determinant, Frobenius norm, or number of eigenvalues > 1 (Kaiser rule). Categorical measures can be summarized as a frequency table - which is, in turn, summarized using metrics such as Gini coefficient, richness, Shannon’s entropy, and Simpson’s index.
Calculating multivariate IIV metrics.
First, set the variables of interest (be sure the id variable is included in the first position)
vars <- c("id", "enthusiastic", "happy", "proud", "relaxed", "calm",
"sluggish", "sad", "disappointed", "angry", "nervous")
Calculate the metrics. Each one takes a few steps
# remove ID 218 (due to zero variance in several items)
AMIB_daily_sub <- AMIB_daily[AMIB_daily$id!=218, ]
#calculating the determinant for each individual
istat_idet <- ddply(AMIB_daily_sub[ ,vars], "id",
function(x) {
det(cor(x[,-1],use="pairwise.complete.obs",
method="pearson"))} )
#renaming columns
colnames(istat_idet) <- c("id","idet")
#calculating Frobenius norm for each individual
istat_iFnorm <- ddply(AMIB_daily_sub[ ,vars], "id",
function(x) {
norm(cor(x[,-1],use="pairwise.complete.obs",
method="pearson"),type="F")} )
#renaming columns
colnames(istat_iFnorm) <- c("id","iFnorm")
Merging all together
istats_multivar <- merge(istat_idet,istat_iFnorm, by="id")
Look at multivariate IIV metrics data
round(head(istats_multivar),2)
## id idet iFnorm
## 1 203 0.00 5.64
## 2 204 0.00 5.11
## 3 205 0.03 4.01
## 4 208 0.00 4.43
## 5 211 0.00 4.72
## 6 214 0.00 4.92
Describe the bivariate IIV metrics.
describe(istats_multivar[ ,-1])
## vars n mean sd median trimmed mad min max range skew kurtosis
## idet 1 29 0.01 0.01 0.00 0.00 0.00 0.00 0.04 0.04 2.00 2.94
## iFnorm 2 29 4.89 0.65 4.89 4.83 0.56 3.97 6.98 3.01 1.04 1.66
## se
## idet 0.00
## iFnorm 0.12
Correlations among the bivariate IIV metrics
round(cor(istats_multivar[ ,-1], use="pairwise.complete.obs"),2)
## idet iFnorm
## idet 1.00 -0.64
## iFnorm -0.64 1.00
Merge the multivariate IIV metrics with other person-level data.
AMIB_multivariate <- merge(istats_multivar, AMIB_persons, by="id")
Examine relation between emotion system variability and neuroticism.
Look at association between idet
and bfi_n
:
pdf("MultivariateIIV.pdf",height=3, width=5)
ggplot(data=AMIB_multivariate, aes(x=bfi_n, y=idet)) +
geom_point(colour="gray40") +
geom_smooth(aes(group=1), method=lm, se=TRUE, fullrange=TRUE, lty=1, size=2, color="#9A23DE") +
xlab("Neuroticism") + ylab("Emotion System\nVariability") +
theme_classic() +
theme(axis.title=element_text(size=16),
axis.text=element_text(size=12),
plot.title=element_text(size=16, hjust=.5)) +
ggtitle("Between-Person Association Multivariate IIV")
dev.off()
## quartz_off_screen
## 2
And the formal model test using (cross-sectional) regression.
reg_multivariate <- lm(idet ~ bfi_n,
data=AMIB_multivariate,
na.action = na.exclude)
summary(reg_multivariate)
##
## Call:
## lm(formula = idet ~ bfi_n, data = AMIB_multivariate, na.action = na.exclude)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0064492 -0.0046937 -0.0038566 0.0003153 0.0305352
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.0082545 0.0064399 1.282 0.211
## bfi_n -0.0009027 0.0018611 -0.485 0.632
##
## Residual standard error: 0.009515 on 27 degrees of freedom
## Multiple R-squared: 0.008638, Adjusted R-squared: -0.02808
## F-statistic: 0.2353 on 1 and 27 DF, p-value: 0.6316
This tutorial illustrated a general approach for calculting intraindividual variability metrics for univariate, bivariate, and multivariate data - metrics that can be used as indicators of specific constructs (e.g., lability, complexity, etc.).
We hope this foundational material prompts consideration of a larger set of intraindivdual variability constructs and the metrics used to operationalize those constructs.
Have fun exploring!