Title: | Calculate the Care Density or Fragmented Care Density Given a Patient-Sharing Network |
---|---|
Description: | Given a patient-sharing network, calculate either the classic care density as proposed by Pollack et al. (2013) <doi:10.1007/s11606-012-2104-7> or the fragmented care density as proposed by Engels et al. (2024) <doi:10.1186/s12874-023-02106-0>. By utilizing the 'igraph' and 'data.table' packages, the provided functions scale well for very large graphs. |
Authors: | Robin Denz [aut, cre] |
Maintainer: | Robin Denz <[email protected]> |
License: | GPL (>= 3) |
Version: | 0.1.0 |
Built: | 2024-12-19 06:25:58 UTC |
Source: | CRAN |
This function calculates the classic Care Density Index as defined by Pollack et al. (2013) for each patient in the supplied dataset. Works well with large patient-sharing networks.
care_density(data, pat_col=1, data_frame=TRUE)
care_density(data, pat_col=1, data_frame=TRUE)
data |
A |
pat_col |
Specifies which column of |
data_frame |
Set this argument to |
The Care Density () is "a patient-level measure that quantifies the amount of patient-sharing among his or her providers" (DuGoff et al. 2018). Higher care densities have been posited to reflect greater connections among a patients "care team". Formally, it is defined as:
with being the number of providers a patient has visited,
defined as the number of all possible combinations of length two and
being the number of patients that a pair of provider is sharing. An example is given below and explained more thoroughly in the vignette of this package.
Under the hood, this function uses the igraph
package to construct a patient-sharing network from the provided data
to calculate the weights. It then uses the data.table
package to efficiently calculate the care densities from a resulting edge list with weights.
Returns a single data.frame
(or data.table
) containing the sum of all weights ("sum_weights"
), the number of providers seen by each patient ("n"
) and the calculated Care Density ("care_density"
).
Robin Denz
Pollack, Craig Evan, Gary E. Weissman, Klaus W. Lemke, Peter S. Hussey, and Jonathan P. Weiner. (2013). "Patient Sharing Among Physicians and Costs of Care: A Network Analytic Approach to Care Coordination Using Claims Data". Journal of General Internal Medicine 28 (3), pp. 459-465.
DuGoff, Eva H., Sara Fernandes-Taylor, Gary E. Weissman, Joseph H. Huntley, and Craig Evan Pollack. (2018). "A Scoping Review of Patient-Sharing Network Studies Using Administrative Data". Translational Behavioral Medicine 8 (4), pp. 598-625.
library(CareDensity) library(data.table) library(igraph) # some arbitrary patient-provider contact data data <- data.frame(PatID=c("1", "1", "1", "2", "2", "3", "3", "4", "5"), ArztID=c("A", "C", "D", "A", "D", "A", "D", "D", "C")) # calculate the care densities care_density(data)
library(CareDensity) library(data.table) library(igraph) # some arbitrary patient-provider contact data data <- data.frame(PatID=c("1", "1", "1", "2", "2", "3", "3", "4", "5"), ArztID=c("A", "C", "D", "A", "D", "A", "D", "D", "C")) # calculate the care densities care_density(data)
This function calculates the Fragmented Care Density Index as defined by Engels et al. (2024) for each patient in the supplied dataset. Works well with large patient-sharing networks.
fragmented_care_density(data, pat_col=1, weights, type, by_connection=FALSE, data_frame=TRUE)
fragmented_care_density(data, pat_col=1, weights, type, by_connection=FALSE, data_frame=TRUE)
data |
A |
pat_col |
Specifies which column of |
weights |
A |
type |
A |
by_connection |
Either |
data_frame |
Set this argument to |
The Fragmented Care Density is an extension of the classic Care Density (see care_density
) and was proposed by Engels et al. (2024). It is also a measure of care coordination, but it allows a lot more flexibility by using different weights for different provider-type connections. For example, it may make sense to weight the amount of patients shared by two general providers differently than the amount of patients shared by a general provider and a specialist. Formally, the fragmented care density is defined as:
where is the number of different providers patient
visited and
are some connection specific weights.
is defined as:
with being the number of different provider types. Finally,
is the sum of the number of patients shared by all doctors of a specific connection type. See Engels et al. (2024) for more information.
Under the hood, this function uses the igraph
package to construct a patient-sharing network from the provided data
to calculate the weights. It then uses the data.table
package to efficiently calculate the care densities from a resulting edge list with weights.
Returns a single data.frame
(or data.table
) containing output depending on the specification of the by_connection
argument.
When by_connection=FALSE
was used the output only includes the patient id ("PatID"
) and the calculated fragmented care densities ("fragmented_care_density"
).
When by_connection=TRUE
was used instead, the output includes the patient id ("PatID"
), the connection-type ("connection"
) the sum of all weights ("sum_weights"
), the number of providers seen by each patient ("n"
) and the calculated simple care density ("care_density"
).
Robin Denz
Pollack, Craig Evan, Gary E. Weissman, Klaus W. Lemke, Peter S. Hussey, and Jonathan P. Weiner. (2013). "Patient Sharing Among Physicians and Costs of Care: A Network Analytic Approach to Care Coordination Using Claims Data". Journal of General Internal Medicine 28 (3), pp. 459-465.
Engels, Alexander, Claudia Konnopka, Espen Henken, Martin Härter, and Hans-Helmut König. (2024). "A Flexible Approach to Measure Care Coordination Based on Patient-Sharing Networks". BMC Medical Research Methodology 24 (1), pp. 1-12.
library(CareDensity) library(data.table) library(igraph) # some arbitrary patient-provider contact data data <- data.frame(PatID=c("1", "1", "1", "2", "2", "3", "3", "4", "5"), ArztID=c("A", "C", "D", "A", "D", "A", "D", "D", "C")) # defining the provider types d_type <- data.frame(ID=c("A", "C", "D"), Type=c("GP", "GP", "Psychiatrist")) # defining the connection-specific weights d_weights <- data.frame(from=c("GP", "GP", "Psychiatrist"), to=c("GP", "Psychiatrist", "Psychiatrist"), weight=c(1.1, 0.8, 1.3)) # calculate the fragmented care densities fragmented_care_density(data, type=d_type, weights=d_weights) # calculate only the connection-specific sums and care-densities per patient # NOTE: "weights" can be set to NULL here because they won't be used fragmented_care_density(data, type=d_type, weights=NULL, by_connection=TRUE)
library(CareDensity) library(data.table) library(igraph) # some arbitrary patient-provider contact data data <- data.frame(PatID=c("1", "1", "1", "2", "2", "3", "3", "4", "5"), ArztID=c("A", "C", "D", "A", "D", "A", "D", "D", "C")) # defining the provider types d_type <- data.frame(ID=c("A", "C", "D"), Type=c("GP", "GP", "Psychiatrist")) # defining the connection-specific weights d_weights <- data.frame(from=c("GP", "GP", "Psychiatrist"), to=c("GP", "Psychiatrist", "Psychiatrist"), weight=c(1.1, 0.8, 1.3)) # calculate the fragmented care densities fragmented_care_density(data, type=d_type, weights=d_weights) # calculate only the connection-specific sums and care-densities per patient # NOTE: "weights" can be set to NULL here because they won't be used fragmented_care_density(data, type=d_type, weights=NULL, by_connection=TRUE)
This function takes a bipartite network created using the igraph
package and returns an adjacency matrix of one of its underlying modes. By directly allowing sparse matrices it is faster and more RAM efficient than some other available versions.
project_to_one_mode(g, mode, sparse=TRUE)
project_to_one_mode(g, mode, sparse=TRUE)
g |
An |
mode |
Either |
sparse |
Whether to use sparse matrix representations or not. Must be either |
A bipartite graph only has connections between two types of nodes. For example, one type of node may be the providers and the other type may be patients. In health-care databases we would usually see which patient visited which providers, but we would not see any direct links between providers and patients. This type of graph can be projected into two subgraphs. One which only includes the providers and one which only includes the patients. This function efficiently creates adjacency matrices of these projections.
The resulting adjacency matrix is a symmetric square matrix that contains the number of shared patients (in provider level graphs) or the number of shared providers (in the patient level graph). See the examples below.
Returns a sparse adjacency matrix of the specified mode.
Robin Denz
Landon, Bruce E., Nancy L. Keating, Michael L. Barnett, Jukka-Pekka Onnela, Sudeshna Paul, A. James O’Malley, Thomas Keegan, and Nicholas A. Christakis. (2012). "Variation in Patient-Sharing Networks of Physicians Across the United States". JAMA 308 (3): 265–73.
library(CareDensity) library(igraph) # some arbitrary patient-provider contact data data <- data.frame(PatID=c("1", "1", "1", "2", "2", "3", "3", "4", "5"), ArztID=c("A", "C", "D", "A", "D", "A", "D", "D", "C")) # create graph g <- graph_from_data_frame(data, directed=FALSE) # add type V(g)$type <- bipartite_mapping(g)$type ## NOTE: we use sparse=FALSE here to show the resulting matrix directly, # but it would be more efficient to keep it at sparse=TRUE # project to patient-level project_to_one_mode(g, mode="rows", sparse=FALSE) # project to provider-level project_to_one_mode(g, mode="cols", sparse=FALSE)
library(CareDensity) library(igraph) # some arbitrary patient-provider contact data data <- data.frame(PatID=c("1", "1", "1", "2", "2", "3", "3", "4", "5"), ArztID=c("A", "C", "D", "A", "D", "A", "D", "D", "C")) # create graph g <- graph_from_data_frame(data, directed=FALSE) # add type V(g)$type <- bipartite_mapping(g)$type ## NOTE: we use sparse=FALSE here to show the resulting matrix directly, # but it would be more efficient to keep it at sparse=TRUE # project to patient-level project_to_one_mode(g, mode="rows", sparse=FALSE) # project to provider-level project_to_one_mode(g, mode="cols", sparse=FALSE)