I have a dataframe in R that looks something like this:
library(tibble)
sample <- tribble(~subj, ~session,
"A", 1,
"A", 2,
"A", 3,
"B", 1,
"B", 2,
"C", 1,
"C", 2,
"C", 3,
"C", 4)
Run Code Online (Sandbox Code Playgroud)
As you can see from this example, there are a number of sessions for each subject, but subjects do not all have the same number of sessions. There are 94 rows in my real dataset (5 subjects, between 15 and 20 different sessions each).
I have another script that takes my main dataset (a set of linguistic data with detailed phonetic features for each subject in each session, with almost 200,000 rows) and filters by subject and session to create a distance matrix showing Euclidean distances between the different words. I can't replicate it here for practical reasons, but have created an example script here:
library(tibble)
data <- tribble(~subj, ~session, ~Target, ~S1C1_target, # S1C1 = syllable 1, consonant 1
~S1C1_T.Sonorant, ~S1C1_T.Consonantal, # _T. = target consonant of S1C1
~S1C1_T.Voice, ~S1C1_T.Nasal, ~S1C1_T.Degree, # .Voice/.Nasal/etc are phonetic
# properties of the target word
"A", 1, "electricity", "i", 0, 0, 0, 0, 0,
"A", 1, "hectic", "h", 0.8, 0, 1, 0, 0,
"A", 1, "pillow", "p", -1, 1, -1, 0, 0,
"A", 2, "hello", "h", -0.5, 1, 0, -1, 0,
"A", 2, "cup", "k", 0.8, 0, 1, 0, 0,
"A", 2, "exam", "e", 0, 0, 0, 0, 0,
"B", 1, "wug", "w", 0.8, 0, 1, 0, 0,
"B", 1, "wug", "w", 0.8, 0, 1, 0, 0,
"B", 1, "hug", "h", 0.8, 0, 1, 0, 0,
"B", 2, "wug", "w", -0.5, 1, 0, -1, 0,
"B", 2, "well", "w", 0.8, 0, 1, 0, 0,
"B", 2, "what", "w", 0.8, 0, 1, 0, 0)
Run Code Online (Sandbox Code Playgroud)
I want to start by creating a sub-set of data for each subject in each session. Sometimes a participant has more than one token of the same word in Target, so I create a mean value for repeated iterations here as well:
matrixA1 <- data %>% # name the data after the subj and session name/number
filter(subj == "A" & session == 1) %>%
dplyr::select(-subj, -session) %>% # leave only the numeric values + `Target`
group_by(Target) %>%
summarize_all(.funs = list(mean)) # Average across targets with more than one token
##### Calculate Euclidean distance between each phonetic property of each S1C1 target consonant
ones <- rep(1,nrow(matrixA1)) # count repeated rows
Son.mat.S1C1_T <- matrixA1$S1C1_T.Sonorant %*% t(ones) - ones %*% t(matrixA1$S1C1_T.Sonorant)
rownames(Son.mat.S1C1_T) <- matrixA1$Target
colnames(Son.mat.S1C1_T) <- matrixA1$Target
colnames(Son.mat.S1C1_T) <- paste(colnames(Son.mat.S1C1_T), "Son.S1C1_T", sep = "_")
Son.mat.S1C1_T <- Son.mat.S1C1_T^2
Con.mat.S1C1_T <- matrixA1$S1C1_T.Consonantal %*% t(ones) - ones %*% t(matrixA1$S1C1_T.Consonantal)
rownames(Con.mat.S1C1_T) <- matrixA1$Target
colnames(Con.mat.S1C1_T) <- matrixA1$Target
colnames(Con.mat.S1C1_T) <- paste(colnames(Con.mat.S1C1_T), "Con.S1C1_T", sep = "_")
Con.mat.S1C1_T <- Con.mat.S1C1_T^2
Voice.mat.S1C1_T <- matrixA1$S1C1_T.Voice %*% t(ones) - ones %*% t(matrixA1$S1C1_T.Voice)
rownames(Voice.mat.S1C1_T) <- matrixA1$Target
colnames(Voice.mat.S1C1_T) <- matrixA1$Target
colnames(Voice.mat.S1C1_T) <- paste(colnames(Voice.mat.S1C1_T), "Voice.S1C1_T", sep = "_")
Voice.mat.S1C1_T <- Voice.mat.S1C1_T^2
Nasal.mat.S1C1_T <- matrixA1$S1C1_T.Nasal %*% t(ones) - ones %*% t(matrixA1$S1C1_T.Nasal)
rownames(Nasal.mat.S1C1_T) <- matrixA1$Target
colnames(Nasal.mat.S1C1_T) <- matrixA1$Target
colnames(Nasal.mat.S1C1_T) <- paste(colnames(Nasal.mat.S1C1_T), "Nasal.S1C1_T", sep = "_")
S1C1.1A <- Son.mat.S1C1_T +
Con.mat.S1C1_T +
Voice.mat.S1C1_T +
Nasal.mat.S1C1_T
colnames(S1C1.1A) = gsub("_Son.S1C1_T", "", colnames(S1C1.1A))
Run Code Online (Sandbox Code Playgroud)
This creates a matrix that looks something like this:
electricity hectic pillow
electricity 0.00 1.64 3.00
hectic 1.64 0.00 8.24
pillow 3.00 8.24 0.00
Run Code Online (Sandbox Code Playgroud)
As you can see, this code is already quite big, and the real code is quite a lot longer. I know that a loop of some kind will be the best way to deal with it, but I can't figure out how to run it. What I would like it to do is this:
sample, create a dataframe that has subj and session as identifiers in the name#####, to create a matrix for each subject and each session, like the one shown above.To do this, I think the best way is to embed the script into a for-loop, and specify that it should be run for each row in sample.
在我看来,您不需要引用您的数据框,因为有关和sample组合的信息都在您的. 如果情况并非如此,请告诉我。否则,这是我的方法。subjsessiondata
首先,在根据主题会话组合对数据进行分组后,无需手动过滤 和 的每个组合的数据,而是一次性过滤subj数据session。summarize在此之前,给每个组合一个idwith group_indices:
data_summ <- data %>% \n mutate(id = group_indices(., subj, session)) %>%\n group_by(subj, session, Target) %>% \n summarize_all(.funs = list(mean))\nRun Code Online (Sandbox Code Playgroud)\n\n现在,您可以使用列表方法来提高透明度。首先将汇总数据拆分为一系列数据框,每个数据框对应一个主题会话id:
data_list <- data_summ %>%\n split(., f = .$id)\nRun Code Online (Sandbox Code Playgroud)\n\n现在您可以通过 获取第一个数据帧data_list[[1]],通过 获取第二个数据帧,data_list[[2]]依此类推。这允许您循环遍历列表并计算每个列表元素的矩阵。我简化了您的一些代码 - 例如,您不需要重新命名四个矩阵(基于S1C1_T.Consonantal,S1C1_T.Consonantal...)。我建议您将所有结果存储在一个名为 的单独列表中mat_list。
mat_list = list()\n\nfor (i in 1:length(data_list)) {\n\n element <- data_list[[i]]\n\n ones <- rep(1, nrow(element))\n\n sonorant_vec <- element$S1C1_T.Sonorant\n sonorant_mat <- (sonorant_vec %*% t(ones) - ones %*% t(sonorant_vec))^2\n\n consonantal_vec <- element$S1C1_T.Consonantal\n consonantal_mat <- (consonantal_vec %*% t(ones) - ones %*% t(consonantal_vec))^2\n\n voice_vec <- element$S1C1_T.Voice\n voice_mat <- (voice_vec %*% t(ones) - ones %*% t(voice_vec))^2\n\n nasal_vec <- element$S1C1_T.Nasal\n nasal_mat <- (nasal_vec %*% t(ones) - ones %*% t(nasal_vec))^2\n\n all_mat <- sonorant_mat + consonantal_mat + voice_mat + nasal_mat\n rownames(all_mat) <- element$Target\n colnames(all_mat) <- element$Target\n\n mat_list[[i]] <- all_mat\n}\nRun Code Online (Sandbox Code Playgroud)\n\n等等\xc3\xa0:
\n\n[[1]]\n electricity hectic pillow\nelectricity 0.00 1.64 3.00\nhectic 1.64 0.00 8.24\npillow 3.00 8.24 0.00\n\n[[2]]\n cup exam hello\ncup 0.00 1.64 4.69\nexam 1.64 0.00 2.25\nhello 4.69 2.25 0.00\n\n[[3]]\n hug wug\nhug 0 0\nwug 0 0\n\n[[4]]\n well what wug\nwell 0.00 0.00 4.69\nwhat 0.00 0.00 4.69\nwug 4.69 4.69 0.00\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:\n如果你想避免 for 循环,你可以将循环内的块放入一个函数中,然后lapply将其data_list:
lapply(data_list, FUN = function(element) {\n\n ones <- rep(1, nrow(element))\n\n sonorant_vec <- element$S1C1_T.Sonorant\n sonorant_mat <- (sonorant_vec %*% t(ones) - ones %*% t(sonorant_vec))^2\n\n consonantal_vec <- element$S1C1_T.Consonantal\n consonantal_mat <- (consonantal_vec %*% t(ones) - ones %*% t(consonantal_vec))^2\n\n voice_vec <- element$S1C1_T.Voice\n voice_mat <- (voice_vec %*% t(ones) - ones %*% t(voice_vec))^2\n\n nasal_vec <- element$S1C1_T.Nasal\n nasal_mat <- (nasal_vec %*% t(ones) - ones %*% t(nasal_vec))^2\n\n all_mat <- sonorant_mat + consonantal_mat + voice_mat + nasal_mat\n rownames(all_mat) <- element$Target\n colnames(all_mat) <- element$Target\n\n return(all_mat)\n})\nRun Code Online (Sandbox Code Playgroud)\n\n编辑2
\n\n要根据主题会话组合名称命名列表元素,您可以执行以下操作:
\n\ndata_summ <- data %>% \n group_by(subj, session, Target) %>% \n summarize_all(.funs = list(mean)) %>%\n mutate(subj_session = paste(subj, session))\nRun Code Online (Sandbox Code Playgroud)\n\n然后根据这个新的subj_session标识符分割数据:
data_list <- data_summ %>%\n split(., f = .$subj_session)\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
278 次 |
| 最近记录: |