Related
I am an ICU physician conducting research which involves taking lots of patient-related data from the ICU computer system (all ethically approved, etc). As is often the case, getting data out then requires cleaning and wrangling before it can be used properly.
I have obtained a set of data, and have wrangled it as best I can. Of course, my data science skills are pretty rudimentary and despite being an enthusiastic R user, I am at a complete blockage, and am hoping some of you might be able to shed some light on my problem and how to solve it. I absolutely cannot get round this, but suspect it is a commonly encountered issue in time-series work.
At present, my dataset now includes multiple rows for each time point. So, at time X there is an individual row for heart rate, blood pressure, etc. There are 46 observations, and this repeats for every time point (344 in total for this patient). All observations are not recorded at each time point. I have provided a link to screenshots of the way this data is arranged here.
A sample of the data is here, is that helps.
The best progress I've made is with the following nested for-loop structure. It works for the first set of observations. I have tried a strange while-loop arrangement that fell flat on its face.
# First, add a group to the entire table specifying each time point that
# observations were conducted.
Patient_full$Verification_group <- as.numeric(as.factor(Patient_full$Time))
# Get the number of these groups
observation_times <- max(Patient_full$Verification_group)
# Create the bare bones of an overall table. This is the first row of the table.
patient_obs_final <- Patient_full[1,]
# Next I need to create a loop within loop. The master loop will coerce rows
# that have been created by the sub-loop.
for (i in 1 : observation_times) {
# Isolate the overall observation group you are dealing with
veri_group <- filter(Patient_full, Verification_group == i)
# Start by getting some numbers to run the sub-loop
lowest_obs_time_row <- min(veri_group$Row)
highest_obs_time_row <- max(veri_group$Row)
rows_in_obs_time <- (highest_obs_time_row - lowest_obs_time_row)
# We can run the sub-loop now
obs_at_timepoint <- Patient_full[lowest_obs_time_row, ]
for (j in 1 : (rows_in_obs_time - 1)) {
obs_at_timepoint <- coalesce(obs_at_timepoint, Patient_full[j + 1,])
}
patient_obs_final <- rbind(patient_obs_final, obs_at_timepoint)
}
patient_obs_final
As soon as j goes to 2 the thing seems to fall apart.
So, in the end my goal is to have a separate row for each time point, and for that row to have whatever was recorded/observed at that time. I am at a loss, and can't even tell why my solution isn't working. Any advice would be greatly appreciated.
Try this dplyr solution:
library(dplyr)
dat %>%
group_by(Time) %>%
mutate(
Cardiac.Rhythm = if_else(nzchar(Cardiac.Rhythm), Cardiac.Rhythm, NA_character_),
across(-Row, ~ .[order(is.na(.))])
) %>%
ungroup() %>%
filter(rowSums(!is.na(.)) > 2) %>%
as.data.frame()
# Row Time Base.excess..vt. Glucose.ABG Lactate.ABG PaCO2 PaO2 PH..ABG. Potassium.ABG Sodium.ABG Cardiac.Rhythm Arterial.Pressure.Diastolic Arterial.Pressure.Mean Arterial.Pressure.Systolic Heart.Rate
# 1 1 2017-09-04 17:00:00 -11.4 11.8 10.7 4.42 31.5 7.25 3.9 3.9 ST NA NA NA NA
# 2 10 2017-09-04 17:55:00 NA NA NA NA NA NA NA NA <NA> 54 68 92 123
# 3 14 2017-09-04 18:00:00 NA NA NA NA NA NA NA NA ST 60 71 86 123
# 4 23 2017-09-04 19:00:00 -9.3 10.1 9.7 4.22 15.0 7.30 3.9 3.9 ST 58 70 92 122
# 5 36 2017-09-04 20:00:00 -8.4 8.1 7.2 5.07 16.9 7.27 3.9 3.9 ST 62 80 117 NA
(I truncated the columns pasted here ...)
Walk-through:
For some reason, Cardiac.Rhythm has empty strings instead of NA, the first mutate converts empty strings "" to NA so that later filtering works;
.[order(is.na(.))] orders the non-NA data first within each column;
rowSums(.) ensures that we have at least one non-NA datum on a row (the > 2 takes into account that Row and Time are not NA).
Notes:
I assume that data is one "person" per frame; if you have a patient id in the data, make sure to add it within the group_by(.) as well.
Within a particular Time (and Patient_ID, if present), I assume that the order of rows is not important (ergo the per-column reordering of values).
I do not assume that each column can have only one value per Time; while logically it makes sense that this would be the case, there could also be an error in the data-scraping/aggregation before this point, so I intentionally do not assume that x[!is.na(x)] (when grouped by Time) will always return length 1. This will evidence as two (or more) rows in a specific Time.
I thought about using pivot_longer for this, and it still might be possible, but ... you have both numeric and character data here, so it's a little problematic to sort that out well.
Data
dat <- structure(list(Row = 1:47, Time = c("2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:00:00", "2017-09-04 17:55:00", "2017-09-04 17:55:00", "2017-09-04 17:55:00", "2017-09-04 17:55:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 18:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 19:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00", "2017-09-04 20:00:00" ), Base.excess..vt. = c(-11.4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -9.3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -8.4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Glucose.ABG = c(NA, 11.8, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 10.1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 8.1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Lactate.ABG = c(NA, NA, 10.7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 9.7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 7.2, NA, NA, NA, NA, NA, NA, NA, NA, NA), PaCO2 = c(NA, NA, NA, 4.42, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 4.22, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 5.07, NA, NA, NA, NA, NA, NA, NA, NA), PaO2 = c(NA, NA, NA, NA, 31.5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 15, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 16.9, NA, NA, NA, NA, NA, NA, NA), PH..ABG. = c(NA, NA, NA, NA, NA, 7.25, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 7.3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 7.27, NA, NA, NA, NA, NA, NA), Potassium.ABG = c(NA, NA, NA, NA, NA, NA, 3.9, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 3.9, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 3.9, NA, NA, NA, NA, NA), Sodium.ABG = c(NA, NA, NA, NA, NA, NA, 3.9, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 3.9, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 3.9, NA, NA, NA, NA, NA), Cardiac.Rhythm = c("", "", "", "", "", "", "", "", "ST", "", "", "", "", "", "", "", "ST", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ST", "", "", "", "", "", "", "", "", "", "", "", "", "ST"), Arterial.Pressure.Diastolic = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 54L, NA, NA, NA, 60L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 58L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62L, NA, NA, NA), Arterial.Pressure.Mean = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 68L, NA, NA, NA, 71L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 70L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 80L, NA, NA), Arterial.Pressure.Systolic = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 92L, NA, NA, NA, 86L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 92L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 117L, NA ), Heart.Rate = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 123L, NA, NA, NA, NA, 123L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 122L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Non.Invasive.Arterial.Pressure.Diastolic = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 58L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Non.Invasive.Arterial.Pressure.Mean = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 71L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Non.Invasive.Arterial.Pressure.Systolic = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 108L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Tympanic.Temperature = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 37.6, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Patient.Positioning.ABG = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Central.Venous.Pressure = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Delivered.Percent.O2 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Mean.Airway.Pressure.S = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Minute.Volume.expired..S. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Peak.Inspiratory.Pressure.measured..S = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Positive.End.Expiratory.pressure = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), S.Expired.Tidal.vol...breath. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), S.Tidal.Volume.Inspired = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Servo.i.Modes = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Set.FiO2 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Set.Flow.Trigger.S = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA ), Set.Pause.time.. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Set.PEEP.Servo = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA ), Set.rate..CMV.or.SIMV. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Set.Tidal.Volume..servo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Set.Upper.Pressure.Limit = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Spontaneous.Rate..S = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Cardiac.output..Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), DO2.Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), DO2I.Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Stroke.Volume.Index.Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Stroke.Volume.Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Systemic.Vascular.Resistance.Index.Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Systemic.Vascular.Resistance.Vigileo. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Ionised.Calcium.ABG = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Set.Pressure.Control.level.above.PEEP.S. = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, -47L))
Don't do it in a loop. Only one summarise_at is enough !!
library(tidyverse)
Patient_01_sample <- read.csv("E:/R/StackOverflow/Patient_01_sample.xlsx - Sheet 1.csv", row.names=1)
f = function(x) ifelse(length(x[!is.na(x)])==0,NA,x[!is.na(x)][1])
Patient = read_csv("Patient_01_sample.xlsx - Sheet 1.csv")
Patient %>% group_by(Time) %>%
summarise_at(vars(3:45), f)
output
# A tibble: 5 x 44
Time `Glucose ABG` `Lactate ABG` PaCO2 PaO2 `PH (ABG)` `Potassium ABG` `Sodium ABG` `Cardiac Rhythm` `Arterial Pressure Di~
<dttm> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
1 2017-09-04 17:00:00 11.8 10.7 4.42 31.5 7.25 3.9 3.9 ST NA
2 2017-09-04 17:55:00 NA NA NA NA NA NA NA NA 54
3 2017-09-04 18:00:00 NA NA NA NA NA NA NA ST 60
4 2017-09-04 19:00:00 10.1 9.7 4.22 15 7.3 3.9 3.9 ST 58
5 2017-09-04 20:00:00 8.1 7.2 5.07 16.9 7.27 3.9 3.9 ST 62
# ... with 34 more variables: Arterial Pressure Mean <dbl>, Arterial Pressure Systolic <dbl>, Heart Rate <dbl>,
# Non Invasive Arterial Pressure Diastolic <dbl>, Non Invasive Arterial Pressure Mean <dbl>,
# Non Invasive Arterial Pressure Systolic <dbl>, Tympanic Temperature <dbl>, Patient Positioning ABG <lgl>, Central Venous Pressure <lgl>,
# Delivered Percent O2 <lgl>, Mean Airway Pressure S <lgl>, Minute Volume expired (S) <lgl>, Peak Inspiratory Pressure measured S <lgl>,
# Positive End Expiratory pressure <lgl>, S Expired Tidal vol. (breath) <lgl>, S Tidal Volume Inspired <lgl>, Servo i Modes <lgl>,
# Set FiO2 <lgl>, Set Flow Trigger S <lgl>, Set Pause time % <lgl>, Set PEEP Servo <lgl>, Set rate (CMV or SIMV) <lgl>,
# Set Tidal Volume (servo) <lgl>, Set Upper Pressure Limit <lgl>, Spontaneous Rate S <lgl>, Cardiac output (Vigileo) <lgl>, ...
As #r2evans pointed out, this cal also be done with dplyr::pivot_wider.
As he suggested, we need a little hack, that is, to transform all columns to character, then back to their original classes after changing back to wide with pivot_wider
library(readxl)
library(dplyr)
df<-read.xlsx("Patient_01_sample.xlsx")
df %>% mutate(`Cardiac Rhythm`=replace(`Cardiac Rhythm`, `Cardiac Rhythm`=='', NA)) %>%
select(-1) %>%
mutate(across(-1, as.character)) %>%
pivot_longer(-1)%>%
group_by(name) %>%
filter(!is.na(value)) %>%
ungroup%>%
pivot_wider(id_cols=Time) %>%
mutate(across(-c(1, `Cardiac Rhythm`), as.numeric))
# A tibble: 5 x 18
Time `Base excess (vt)` `Glucose ABG` `Lactate ABG` PaCO2 PaO2 `PH (ABG)` `Potassium ABG`
<dttm> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2017-09-04 17:00:00 -11.4 11.8 10.7 4.42 31.5 7.25 3.9
2 2017-09-04 17:55:00 NA NA NA NA NA NA NA
3 2017-09-04 18:00:00 NA NA NA NA NA NA NA
4 2017-09-04 19:00:00 -9.3 10.1 9.7 4.22 15 7.3 3.9
5 2017-09-04 20:00:00 -8.4 8.1 7.2 5.07 16.9 7.27 3.9
# … with 10 more variables: Sodium ABG <dbl>, Cardiac Rhythm <chr>, Arterial Pressure Diastolic <dbl>,
# Arterial Pressure Mean <dbl>, Arterial Pressure Systolic <dbl>, Heart Rate <dbl>,
# Non Invasive Arterial Pressure Diastolic <dbl>, Non Invasive Arterial Pressure Mean <dbl>,
# Non Invasive Arterial Pressure Systolic <dbl>, Tympanic Temperature <dbl>
I use the igraph and sf packages.
I have an igraph object whose vertices have spatial coordinates geo_dist_graph.
The vertices names and coordinates look like this:
grid_grid <-
structure(list(coords.x1 = c(15.504078, 15.704078, 15.904078,
15.104078, 15.304078, 15.504078, 15.704078, 15.104078, 15.304078,
15.704078, 14.904078, 14.304078, 13.904078, 14.704078, 13.704078,
14.104078, 14.704078, 14.904078, 13.704078, 13.904078, 14.704078,
13.704078, 13.904078, 14.304078),
coords.x2 = c(43.835623, 43.835623,
43.835623, 44.035623, 44.035623, 44.035623, 44.035623, 44.235623,
44.235623, 44.235623, 44.435623, 44.635623, 44.835623, 44.835623,
45.035623, 45.035623, 45.035623, 45.035623, 45.235623, 45.235623,
45.235623, 45.435623, 45.435623, 45.435623),
g9.nodes = c(27,
28, 29, 40, 41, 42, 43, 55, 56, 58, 69, 81, 94, 98, 108, 110,
113, 114, 123, 124, 128, 138, 139, 141)),
class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
"14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"
))
The graph is from a simple squared adjacency matrix:
geo_dist_graph <-
structure(c(NA, 1, 1, NA, NA, 1, 1, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, 1, NA, NA, NA,
1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, 1, 1, NA, NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA,
NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, 1, NA, 1, NA, NA, 1, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, NA, 1, NA,
1, NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, 1, 1, 1, NA, NA, 1, NA, NA, NA, 1, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, NA,
NA, 1, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, 1, 1, 1, NA, 1, NA, 1, 1, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 1, NA,
1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, 1, 1, NA, NA, NA, NA, 1, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, 1, 1, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, 1, 1,
NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, 1, 1, NA, NA, NA, NA, 1, 1, NA, NA, 1, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, 1, NA,
NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, 1, 1, NA, 1, NA, NA, NA, NA, 1, NA, NA, NA, 1, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, NA, 1,
NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 1, NA, NA, 1, NA, NA, NA, 1, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, NA,
NA, 1, NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, 1, NA, 1, 1, NA, NA, 1, NA, NA, 1, 1, 1, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, NA, 1, 1, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, 1, 1, NA, NA, 1, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1,
1, NA, 1, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, 1, NA, NA, NA, 1, NA, NA, 1, NA),
.Dim = c(24L,
24L))
colnames(geo_dist_graph) <- grid_grid$g9.nodes
row.names(geo_dist_graph) <- grid_grid$g9.nodes
geo_dist_graph <- graph_from_adjacency_matrix(geo_dist_graph, mode = "upper", diag = F)
The spatial coordinates where attched this way:
V(geo_dist_graph)$x <-
grid_grid$coords.x1[match(V(geo_dist_graph)$name, grid_grid$g9.nodes)]
V(geo_dist_graph)$y <-
grid_grid$coords.x2[match(V(geo_dist_graph)$name, grid_grid$g9.nodes)]
The graph is correclty plotted in space when using the plot function. But when I try to add a basemap like this plot(map_crop_sp, add = T), the map doesn't show behind the graph, but there is no error message.
The map is vector map, don't know if it's important. Here is the code used to create it.
map <- st_read("ne_10m_coastline/ne_10m_coastline.shp")
map_crop <- st_crop(map, xmin = 13.304078, ymin = 43.635623, xmax = 16.503846, ymax = 45.60185)
map_crop_sp <- as(map_crop, Class = "Spatial")
Answer
Since the igraph should be on top of the map, I plot it second. I also added rescale = F:
plot(map_crop_sp)
plot(geo_dist_graph, add = T, rescale = F)
Rationale
I typed ?plot.igraph. From there, I found ?igraph.plotting. It seems that plotting an igraph object rescales it (plot(..., rescale = TRUE):
Logical constant, whether to rescale the coordinates to the [-1,1]x-1,1 interval. This parameter is not implemented for tkplot.
Defaults to TRUE, the layout will be rescaled.
I would like to use Upset plot instead of venn diagram to show overlap between specific groups (20 in total). However, one of the group (number 10) is the most important for me and I would like to present how many unique values is in that specific fraction. I would like to present ~25-30 intersections in total on the graph but uniqueness of group 10 has to be also shown.
I know existence of sets function but I would like to present around 25-30 intersections as mentioned and this 1 group additionally.
Any ideas ?
EDIT:
Added reproducible example:
dput(rep_exp)
structure(list(Gr_4 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, 24.4310955935393, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA), Gr_5 = c(NA, NA, NA, 21.8310535918369,
NA, NA, NA, NA, NA, 20.7254228450715, NA, 27.1619253143803, NA,
NA, NA, NA, NA, NA, NA, 26.6027203831498, NA, NA, NA, NA, NA,
NA, 30.8729830402671, NA, NA, NA), Gr_6 = c(28.8390902059829,
24.67734371881, 22.683139406727, 29.1546773298581, NA, NA, 21.9107159172821,
NA, 22.9230495998744, 26.9880437180908, NA, 32.391666051163,
NA, NA, NA, 21.6001415858001, 23.0239282537894, NA, 21.055168555216,
30.7121903523751, NA, NA, NA, NA, 22.0963548474675, NA, 32.513357598066,
NA, NA, 23.7976852708585), Gr_7 = c(21.4265985064224, NA, NA,
23.0695638371137, NA, NA, NA, NA, NA, 20.7903453146324, NA, 28.2499758022535,
NA, NA, NA, NA, NA, NA, NA, 25.9613085520105, NA, NA, NA, NA,
NA, NA, 29.355377815192, NA, NA, 21.1302512982254), Gr_8 = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 21.8730880931062, NA,
NA, NA, NA, NA, NA, NA, 22.4189005564519, NA, NA, NA, NA, NA,
NA, 30.2275670312356, NA, NA, NA), Gr_9 = c(22.195894810917,
25.9203441316619, NA, 23.5317193622031, NA, NA, NA, 20.4526193062251,
NA, 22.357699113594, 19.9767319209274, 29.0184743803346, NA,
NA, NA, NA, 22.1010446624755, NA, NA, 26.3118997535445, NA, NA,
NA, NA, NA, NA, 29.9658173049532, NA, NA, 22.7388204380555),
Gr_10 = c(24.9716280984187, 26.6702013159945, NA, 26.0197313721615,
NA, NA, NA, 22.1233522815746, NA, 24.0516716332837, 22.4063679987568,
30.256761573029, NA, NA, NA, NA, 26.4434318913431, NA, NA,
27.9654320211905, NA, NA, NA, NA, NA, NA, 29.8212398361126,
NA, NA, 24.1442935303143), Gr_11 = c(22.9856008507804, 25.1691705265075,
NA, 26.0689081411402, NA, NA, NA, 21.1400234004731, NA, 24.5711480491199,
23.5402595534611, 29.329649538014, NA, NA, NA, NA, 28.6076666902364,
NA, NA, 26.5597151498881, NA, NA, 25.8334491330428, NA, NA,
NA, 29.7854239060885, NA, NA, 21.751849665826), Gr_12 = c(28.2942576160509,
28.4109042369708, NA, 30.2938411874268, 28.1159976488766,
26.6893919055319, NA, 20.2236435193017, NA, 31.1236147481775,
27.1394614209655, 33.7497512742728, NA, NA, NA, 22.1620175455317,
32.740995072413, NA, 23.2685659859292, 31.9204662366898,
NA, NA, 30.7601811119423, NA, NA, 22.8704941623247, 31.3416488641037,
NA, NA, 28.6773773257387), Gr_13 = c(27.9415091276483, 27.0299165363222,
NA, 30.7110417097659, 28.7379570773404, 25.5882365428802,
NA, NA, NA, 32.2667076588073, 27.2933369287433, 34.7079501935325,
NA, 22.8206916170467, NA, NA, 32.5779472688676, NA, NA, 32.6317048040664,
NA, NA, 30.1389490092958, 23.8308408919424, 23.0679896658325,
26.164689687244, 30.2006952484736, NA, 24.447772868487, 29.5606883639626
), Gr_14 = c(27.4616237005853, 26.7750499947566, NA, 30.3932526396929,
31.1062446290124, 27.2595253359549, NA, NA, NA, 33.6656430607522,
27.734214173453, 35.0800848727354, NA, NA, NA, 23.151279208873,
33.2366327906614, NA, NA, 33.4932145181405, 22.9608977649923,
NA, 31.8193222893087, 24.7850652730265, NA, 24.9920915833786,
29.0239557410047, 25.2744788247811, 26.6821750741598, 29.7891764054099
), Gr_15 = c(27.2029382158867, 25.3112934881725, NA, 29.1103329989503,
29.514275096105, NA, NA, NA, NA, 31.6854120776358, 28.5249970429603,
35.9001903675862, 22.4465240056921, NA, NA, NA, 31.8450938083269,
25.5788830788713, NA, 34.7663358707296, 25.6549086895753,
26.2291635318221, 31.9466351025545, 26.715548983008, NA,
25.6752720211283, 28.4457302899793, 27.2647239196348, 25.0412216502086,
31.6489022687779), Gr_16 = c(25.1843096821522, NA, NA, 26.444459119903,
23.8302606418847, NA, NA, NA, NA, 27.987230611469, 27.8591095189136,
32.8816869988268, NA, NA, 24.8165571469754, NA, 28.7689442058935,
25.2395434664377, NA, 32.829999906694, 23.6787411063596,
NA, 27.8325560998723, 25.9582137297807, NA, NA, 25.6769403745901,
25.3048339598422, 23.7070405817542, 29.8423911570548), Gr_17 = c(23.2209751780558,
NA, NA, 24.6434488773652, 22.5225058653221, NA, NA, NA, NA,
27.0216809889885, 26.6607134339159, 31.099676534797, NA,
NA, 26.93077937966, NA, 27.8090060912948, 26.7795654758791,
NA, 32.3731900255852, 24.9494014193233, NA, 24.5609834789349,
26.086325932043, NA, NA, 25.5082418618407, 23.6504233402429,
23.8014399755019, 28.7791270904749), Gr_18 = c(NA, NA, NA,
NA, NA, NA, 26.0401348427439, NA, NA, 24.3341543275568, 24.7556235529872,
30.4889365348298, NA, NA, 26.9888022043666, NA, 25.7387173773674,
27.1316334308385, NA, 31.571451882524, NA, NA, NA, 25.745888266175,
NA, NA, 23.2997781674234, NA, NA, 23.2402643606836), Gr_19 = c(NA,
NA, NA, NA, NA, NA, 24.3940790216008, NA, NA, NA, 21.4222413790374,
25.7991932672173, NA, NA, 25.9372380266141, NA, 22.9217973627502,
20.5334552143032, NA, 28.7776543930148, NA, NA, NA, 23.9298543509444,
NA, NA, 24.3614522942989, NA, NA, NA), Gr_20 = c(NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, 25.6961748124338, NA,
NA, NA, NA, NA, NA, NA, 26.4582321196234, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA), Gr_21 = c(NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, 22.8258042878256, NA, NA, NA, NA, NA,
NA, NA, 25.1317511650203, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA)), row.names = c(NA, 30L), class = "data.frame")
It is a code which has been used to generate a plot:
for (i in 1:nrow(rep_exp)) { rep_exp[i, ][is.na(rep_exp[i, ]) == F] = rownames(rep_exp)[i]}
n_sizescale=nrow(rep_exp)*1.2
p1 <- { upset( fromList(rep_exp),
nsets = ncol(rep_exp), nintersects = 35, order.by = "freq", #degree, freq
empty.intersections = "on", number.angles = 0, mb.ratio = c(0.55, 0.45), point.size = 2.5, line.size = 0.8,
text.scale = c(1.3, 1.3, 1, 1, 1, 1), mainbar.y.label = "Number of groups",
sets.x.label = "Groups",
show.numbers = "yes", keep.order = TRUE,
set_size.show = TRUE,
set_size.scale_max = n_sizescale)
}
If I understood correctly the idea of dots below barplot they indicate how many groups can be found in specific intersections and a single dot gives a number for that specific Gr ? Am I right ?
How to force and algorithm to show couple of "interesting" groups as a single dot (show uniqueness of this group) and other as intersections.
Can you (#krassowski) rewrite a code for the package you mentioned ?
I have a data set consisting out of a matrix with quite some NAs. From this, I want to create a dataframe storing both the location and the value of the non-NA values. Via this answer which can be used to get the locations, via tempList <- which(!is.na(dummy),TRUE).
Currently I use a for loop afterwards. Is there a better way to add the values?
Data:
structure(c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, "#000000FF", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, "#000000FF", NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), .Dim = c(10L,
10L))
Desired result:
structure(list(x = c(8, 7), y = c(5, 7), colour = structure(c(1L,
1L), .Label = "#000000FF", class = "factor")), class = "data.frame", row.names = c(NA,
-2L))
Current code:
tempList <- which(!is.na(dummy),TRUE)
changedDF <- data.frame(tempList[,1],tempList[,2])
names(changedDF) <- c("row","column")
for(i in 1:nrow(changedDF)){
changedDF$colour[i] <- dummy[changedDF[i,1],changedDF[i,2]]
}
I'm quite new to R and have been struggling with properly formatting a forest plot I've created.
When I click the "zoom" option in R to open the graph in a new window, it looks as such:
Forest Plot Currently
My main goal is to get the forest plot as compact as possible, i.e. publication quality/style. I currently have wayyyy too much white space in my plot. I think it has something to do with me messing around with the par() function, and now have no clue how to revert to defaults.
#Metafor library
library(metafor)
#ReadXL library to import excel sheet
library(readxl)
#Name the data sheet from the excel file
ACDF<- read_excel("outpatient_ACDF_meta_analysis.xlsx")
#View the data sheet with view(ACDF)
par(mar=c(20,1,1,1))
#This below measures with risk ratios. If you want to measure odds ratios, use argument measure=OR
returnop <- escalc(measure="OR", ai=op_return_OR, bi=op_no_return_OR, ci=ip_return_OR, di=ip_no_return_OR, data=ACDF)
#Generate a Random Effects Model
REmodel<-rma(yi=yi, vi=vi, data=returnop, slab=paste(Author, Year, sep=", "), method="REML")
#Generate a forest plot of the data
forest(REmodel, xlim=c(-17, 6),
ilab=cbind(ACDF$op_return_OR, ACDF$op_no_return_OR, ACDF$ip_return_OR, ACDF$ip_no_return_OR),
ilab.xpos=c(-9.5,-8,-6,-4.5), cex=.75, ylim=c(-1, 27),
psize=1)
### add column headings to the plot
text(c(-9.5,-8,-6,-4.5), 26, c("Return+", "Return-", "Return+", "Return-"))
text(c(-8.75,-5.25), 27, c("Outpatient", "Inpatient"))
text(-16, 26, "Study", pos=4)
text(6, 26, "Log Odds Ratio [95% CI]", pos=2)
I'm not 100% as to how to provide my data otherwise, but I used the dput function to provide as follows. Apologies for the N/As, still fleshing out the data for the future.
structure(list(Study = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA), Author = c("Stieber", "Villavicencio",
"Lied", "Liu", "Garringer", "Joseffer", "Trahan", "Lied", "Sheperd",
"Talley", "Martin", "McGirt", "Adamson", "Fu", "Arshi", "Khanna",
"McClelland", "Purger", "McLellend2", NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Year = c(2005, 2007,
2007, 2009, 2010, 2010, 2011, 2012, 2012, 2013, 2015, 2015, 2016,
2017, 2017, 2017, 2017, 2017, 2017, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA), op_return_OR = c(NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, 1, 3, 2, 16, 257, 7, NA, 5, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), op_no_return_OR = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
596, 769, 992, 4581, 958, 1749, NA, 3120, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_return_OR = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, 8, 9, 2, 257, 2034, 12, NA,
200, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA), ip_no_return_OR = c(NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 589, 641, 482, 16171, 8930, 1744, NA, 46312, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), op_death = c(NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, 1, NA,
1, 0, NA, 2, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA), op_no_death = c(NA, NA, NA, 45, NA,
NA, NA, NA, NA, NA, 596, NA, 993, 4597, NA, 1754, NA, 3125, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), ip_death = c(NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, 0, NA,
0, 42, NA, 2, NA, 20, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA), ip_no_death = c(NA, NA, NA, 64,
NA, NA, NA, NA, NA, NA, 597, NA, 484, 16386, NA, 1754, NA, 46492,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
2979.79797979798), op_thrombo = c(NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 0, NA, NA, 8, 20, 4, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_thrombo = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, 597, NA, NA, 4589, 1195,
1752, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA), ip_thrombo = c(NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 2, NA, NA, 67, 150, 4, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_thrombo = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, 595, NA, NA, 16361, 10814,
1752, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA), op_stroke = c(NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 0, NA, NA, 2, 12, 0, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_stroke = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, 597, NA, NA, 4595, 1203,
1756, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA), ip_stroke = c(NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 2, NA, NA, 14, 132, 0, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_stroke = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, 595, NA, NA, 16414, 10832,
1756, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA), op_dysphagia = c(NA, NA, NA, 0, NA, NA,
NA, NA, NA, NA, NA, NA, 11, NA, NA, NA, NA, 2, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_dysphagia = c(NA,
NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, 618, NA, NA, NA,
NA, 49, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA), ip_dysphagia = c(NA, NA, NA, 1, NA, NA, NA, NA,
NA, NA, NA, NA, 1, NA, NA, NA, NA, 59, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_dysphagia = c(NA,
NA, NA, 63, NA, NA, NA, NA, NA, NA, NA, NA, 273, NA, NA, NA,
NA, 2917, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA), op_hematoma = c(NA, NA, NA, 0, NA, NA, NA, NA,
NA, NA, NA, NA, 1, NA, NA, NA, 1, 4, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_hematoma = c(NA,
NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, 629, NA, NA, NA,
2015, 47, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA), ip_hematoma = c(NA, NA, NA, 1, NA, NA, NA, NA,
NA, NA, NA, NA, 1, NA, NA, NA, 273, 65, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_hematoma = c(NA,
NA, NA, 63, NA, NA, NA, NA, NA, NA, NA, NA, 273, NA, NA, NA,
7791, 1713, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA)), .Names = c("Study", "Author", "Year", "op_return_OR",
"op_no_return_OR", "ip_return_OR", "ip_no_return_OR", "op_death",
"op_no_death", "ip_death", "ip_no_death", "op_thrombo", "op_no_thrombo",
"ip_thrombo", "ip_no_thrombo", "op_stroke", "op_no_stroke", "ip_stroke",
"ip_no_stroke", "op_dysphagia", "op_no_dysphagia", "ip_dysphagia",
"ip_no_dysphagia", "op_hematoma", "op_no_hematoma", "ip_hematoma",
"ip_no_hematoma"), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-35L))
The par option looks ok to me. I changed the ylim option and modified the y location and size of some of the header text as below:
#Generate a forest plot of the data
forest(REmodel, xlim=c(-17, 6),
ylim=c(-1, 10),
ilab=cbind(ACDF$op_return_OR, ACDF$op_no_return_OR, ACDF$ip_return_OR,
ACDF$ip_no_return_OR),
ilab.xpos=c(-9.5,-8,-6,-4.5), cex=.75,
psize=1)
### add column headings to the plot
text(c(-9.5,-8,-6,-4.5), 8.5, c("Return+", "Return-", "Return+", "Return-"),
cex = 0.65)
text(c(-8.75,-5.25), 9.5, c("Outpatient", "Inpatient"))
text(-17, 8.5, "Study", pos=4)
text(6, 8.5, "Log Odds Ratio [95% CI]", pos=2)
This gives the following plot: