I have a df where the first little bit looks like:
>dput(df_long_binned_sound2[1:48,])
structure(list(id = c(20230420, 20230420, 20230420, 20230420,
20230420, 20230420, 20230420, 20230420, 20230420, 20230420, 20230420,
20230420, 20230420, 20230420, 20230420, 20230420, 20230424, 20230424,
20230424, 20230424, 20230424, 20230424, 20230424, 20230424, 20230424,
20230424, 20230424, 20230424, 20230424, 20230424, 20230424, 20230424,
20230424, 20230426, 20230426, 20230426, 20230426, 20230426, 20230426,
20230426, 20230426, 20230426, 20230426, 20230426, 20230426, 20230426,
20230426, 20230426), cons_id = c(1L, 2L, 3L, 4L, 5L, 6L, 7L,
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 16L, 17L, 18L, 19L,
20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L,
33L, 34L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 42L, 43L, 44L, 45L,
46L, 47L), win = c(1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1), sound = c(1, NA, 1.5,
NA, 2, NA, 2.75, NA, 7, NA, 8, NA, 4, NA, 6.5, NA, NA, 4.5, NA,
6, NA, 2, NA, 5.5, NA, 4.66666666666667, NA, 4.8, NA, 6, NA,
4.5, NA, 3, NA, 2.33333333333333, NA, 6, NA, 1, NA, 1, NA, 1.66666666666667,
NA, 4.5, NA, 5), sound2 = c(NA, 1, NA, 1.5, NA, 1.5, NA, 6, NA,
8, NA, 1, NA, 8, NA, 7, 3, NA, 5, NA, 5, NA, 5, NA, 6.5, NA,
8, NA, 6, NA, 5, NA, 5.66666666666667, NA, 3.5, NA, 2, NA, 2.42857142857143,
NA, 1.5, NA, 2, NA, 8, NA, 2.33333333333333, NA)), row.names = c(NA,
-48L), class = c("tbl_df", "tbl", "data.frame"))
I am running some cross-correlation analysis on it and I would like to save the number outputs of ccf()
. I can save all the correlograms using:
ids <- unique(df_long_binned_sound2$id)
for (i in 1:length(ids)){
pdf(file = paste("/Users/myname/Desktop/Current Work/CRTT study - 2022/CRTT - Full/CRTT_r_Full/Wack_A_Mole/CC_CustomBin/CC/plot_", ids[i], ".pdf"),
width = 10, height = 10
)
ccf(df_long_binned_sound2$sound[which(df_long_binned_sound2$id == ids[i])], df_long_binned_sound2$sound2[which(df_long_binned_sound2$id == ids[i])],
na.action = na.pass,
main = paste("Corrected Correlogram \n Pair", ids[i]),
xlim = c(-6, 6)
)
dev.off()
}
and I can print the number outputs using:
for (i in 1:length(ids)){
print(ccf(df_long_binned_sound2$sound[which(df_long_binned_sound2$id == ids[i])],
df_long_binned_sound2$sound2[which(df_long_binned_sound2$id == ids[i])],
na.action = na.pass,
)
)
}
I would like to save the number outputs so that I end up with something like:
id | lag | lag_value |
---|---|---|
20230420 | -9 | -0.145 |
20230420 | -8 | -0.057 |
...
id | lag | lag_value |
---|---|---|
20230420 | 8 | -0.183 |
20230420 | 9 | -0.203 |
20230424 | -9 | 0.234 |
...
I'm sure there is a simple solution but I can't seem to find it. I very optimistically tried and failed with:
df.cff <- data.frame()
for (i in 1:length(ids)){
cff.standin <- ccf(df_long_binned_sound2$sound[which(df_long_binned_sound2$id == ids[i])],
df_long_binned_sound2$sound2[which(df_long_binned_sound2$id == ids[i])],
na.action = na.pass,
)
df.cff <- cbind(df.cff, cff.standin)
}
Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
cannot coerce class ‘"acf"’ to a data.frame
and:
df.cff <- data.frame()
for (i in 1:length(ids)){
cff.standin <- ccf(df_long_binned_sound2$sound[which(df_long_binned_sound2$id == ids[i])],
df_long_binned_sound2$sound2[which(df_long_binned_sound2$id == ids[i])],
na.action = na.pass,
)
df.cff <- rbind(df.cff, cff.standin)
}
Error in rbind(deparse.level, ...) :
invalid list argument: all variables should have the same length
Does anyone know a good way to save the number outputs of ccf()
from a for loop? I am especially interested in a solution that formats the output like the table examples above.
TYIA :)
You need to inspect the ccf
object with View()
or checking it's help page:
Value
An object of class "acf", which is a list with the following elements:
lag A three dimensional array containing the lags at which the acf is estimated.
acf An array with the same dimensions as lag containing the estimated acf.
Thus, you just want to do something like:
cbind(id = ids[i], lag = cff.standin$lag, lag_value = cff.standin$acf)
Now for the full solution:
ids <- unique(df_long_binned_sound2$id)
df_ccf <- c() #empty vector to save results
for (i in ids){ #you can pass the ids directly, instead of their index
df1_subset <- df_long_binned_sound2[which(df_long_binned_sound2$id == i),] #saving an extra variable saves space in the call below
ccf_output <- ccf(df1_subset$sound, df1_subset$sound2,
na.action = na.pass,
main = paste("Corrected Correlogram \n Pair", i),
xlim = c(-6, 6)
)
df_ccf <- rbind(df_ccf, cbind(id = i, lag = ccf_output$lag, lag_value = ccf_output$acf)) #iteratively rbind the results
}
But I prefer something using tidyverse:
df_ccf <- df_long_binned_sound2 %>%
group_split(id) %>%
imap_dfr(function(data, index){
ccf(data$sound, data$sound2,
na.action = na.pass,
main = paste("Corrected Correlogram \n Pair", i),
xlim = c(-6, 6)) %>%
{tibble(id = ids[index],
lag = as.numeric(.$lag),
lag_value = as.numeric(.$acf))}
})