infinito - R División/subconjunto dinámico de la dataframe por los números de escala seleccionados- Análisis de textgrid praat
seleccionar filas en r (2)
La longitud del vector split
debe ser igual al número de filas en el data.frame
.
Pruebe lo siguiente:
txtgrid.sub <- txtgrid[-(1:grep("item", txtgrid$object)[1]), ]
grep("item", txtgrid.sub$object)[-1]
splits <- unlist(mapply(rep, seq_along(grep("item", txtgrid.sub$object)),
diff(c(grep("item", txtgrid.sub$object),
nrow(txtgrid.sub) + 1))))
df.list <- split(txtgrid.sub, list(splits))
EDITAR:
A continuación, puede simplificar los datos haciendo algo como esto:
l <- lapply(df.list, function(x) {
tmp <- as.data.frame(t(x[, 3, drop=FALSE]), stringsAsFactors=FALSE)
names(tmp) <- make.unique(make.names(x[, 2]))
tmp
})
library(plyr)
do.call(rbind.fill, l)
item..1.. class name xmin xmax intervals..size
1 <NA> IntervalTier phones 0 243.761 2505
2 <NA> IntervalTier syllable 0 243.761 2505
intervals..1.. xmin.1 xmax.1 text intervals..2..
1 <NA> 0 0.4274939687384032 _ <NA>
2 <NA> 0 0.4274939687384032 _ <NA>
xmin.2 xmax.2
1 0.4274939687384032 0.472
2 <NA> <NA>
NB: He utilizado datos ficticios para lo anterior.
Estoy tratando de procesar un "archivo de segmentación" llamado .TextGrid
(generado por el programa Praat). )
El formato original se ve así:
File type = "ooTextFile"
Object class = "TextGrid"
xmin = 0
xmax = 243.761375
tiers? <exists>
size = 17
item []:
item [1]:
class = "IntervalTier"
name = "phones"
xmin = 0
xmax = 243.761
intervals: size = 2505
intervals [1]:
xmin = 0
xmax = 0.4274939687384032
text = "_"
intervals [2]:
xmin = 0.4274939687384032
xmax = 0.472
text = "v"
intervals [3]:
[...]
(Esto luego se repite en EOF, con intervalos [3 a n] para n Item (capa de anotación) en un archivo.
Alguien propuso una solución usando el paquete rPython R.
Desafortunadamente :
- No tengo un buen conocimiento de Python
- La versión de rPython no está disponible para R.3.0.2 (que estoy usando).
- Mi objetivo es desarrollar este analizador para mi análisis exclusivamente en el entorno R.
En este momento mi objetivo es segmentar este archivo en múltiples marcos de datos. Cada marco de datos debe contener un elemento (capa de anotación).
# Load the Data
txtgrid <- read.delim("./xxx_01_xx.textgrid", sep=c("=","/n"), dec=".", header=FALSE)
# Erase White spaces (use stringr package)
txtgrid[,1] <- str_trim(txtgrid[,1])
# Convert row.names to numeric
num.row<- as.numeric(row.names(txtgrid))
# Redefine the original textgrid and add those rows (I want to "keep them in case for later process)
txtgrid <- data.frame(num.row,txtgrid)
colnames(txtgrid) <- c("num.row","object", "value")
head(txtgrid)
La salida de head(txtgrid)
es muy cruda, así que aquí están las primeras 20 líneas de la txtgrid de txtgrid[1:20,]
:
num.row object value
1 1 File type ooTextFile
2 2 Object class TextGrid
3 3 xmin 0
4 4 xmax 243.761375
5 5 tiers? <exists>
6 6 size 17
7 7 item []:
8 8 item [1]:
9 9 class IntervalTier
10 10 name phones
11 11 xmin 0
12 12 xmax 243.761
13 13 intervals: size 2505
14 14 intervals [1]:
15 15 xmin 0
16 16 xmax 0.4274939687384032
17 17 text _
18 18 intervals [2]:
19 19 xmin 0.4274939687384032
20 20 xmax 0.472
Ahora que lo preprocesé, puedo:
# Find the number of the rows where I want to split (i.e. Item)
tier.begining <- txtgrid[grep("item", txtgrid$object, perl=TRUE), ]
# And save those numbers in a variable
x <- as.numeric(row.names(tier.begining))
Esta variable x
me da los números-1 donde mis datos deberían dividirse en varios marcos de datos.
Tengo 18 elementos -1 (el primer elemento es el elemento [] e incluye todos los demás elementos. Entonces el vector x
es:
x
[1] 7 8 10034 14624 19214 22444 25674 28904 31910 35140 38146 38156 38566 39040 39778 40222 44800
[18] 45018
¿Cómo puedo decirle a R : para segmentar este marco de datos en marcos de datos múltiples textgrids textgrids$nameoftheItem
de tal manera que obtenga tantos marcos de datos como tengo de elementos ?, por ejemplo:
textgrid$phones
item [1]:
class = "IntervalTier"
name = "phones"
xmin = 0
xmax = 243.761
intervals: size = 2505
intervals [1]:
xmin = 0
xmax = 0.4274939687384032
text = "_"
intervals [2]:
xmin = 0.4274939687384032
xmax = 0.472
text = "v"
[...]
intervals [n]:
textgrid$syllable
item [2]:
class = "IntervalTier"
name = "syllable"
xmin = 0
xmax = 243.761
intervals: size = 1200
intervals [1]:
xmin = 0
xmax = 0.500
text = "ve"
intervals [2]:
[...]
intervals [n]:
textgrid$item[n]
Yo quería usar
txtgrid.new <- split(txtgrid, f=x)
Pero este mensaje es correcto:
Warning message: In split.default(x = seq_len(nrow(x)), f = f, drop = drop, ...) : data length is not a multiple of split variable
No obtengo el resultado deseado, parece que los números de filas no se siguen y que el archivo está mezclado.
¡También probé algunas daply
(de plyr
) y subset
pero nunca conseguí que funcionaran correctamente!
Estoy dando la bienvenida a cualquier idea para estructurar esta información de manera adecuada y eficiente. Idealmente, debería ser capaz de vincular elementos (capas de anotación) entre ellos (xmin y xmax de diferentes capas), así como varios archivos de cuadrícula de texto, esto es solo el comienzo.
Parece que encontraste una buena solución en otro lugar, pero pensé que sería mejor poner esto aquí para referencia:
Recientemente terminé una primera versión de trabajo de un convertidor JSON para objetos Praat que podría haberse utilizado para esto. Puede guardar el TextGrid como un archivo JSON utilizando el script save_as_json.praat
incluido en este complemento (nuevamente: soy el autor de ese complemento).
Copiado de esta otra respuesta a una pregunta similar, una vez que haya instalado el complemento, puede usar el script desde el menú Save
en Praat o ejecutarlo así desde otro script:
runScript: preferencesDirectory$ + "/plugin_jjatools/save_as_json.praat",
..."/output/path", "Pretty printed"
Una vez hecho esto, puedes leerlo en R
usando rjson
como este:
> library(rjson)
> tg <- fromJSON(file=''/path/to/your_textgrid.json'')
> str(tg)
List of 5
$ File type : chr "json"
$ Object class: chr "TextGrid"
$ start : num 0
$ end : num 1.82
$ tiers :List of 2
..$ :List of 5
.. ..$ class : chr "IntervalTier"
.. ..$ name : chr "keyword"
.. ..$ start : num 0
.. ..$ end : num 1.82
.. ..$ intervals:List of 3
.. .. ..$ :List of 3
.. .. .. ..$ start: num 0
.. .. .. ..$ end : num 0.995
.. .. .. ..$ label: chr ""
.. .. ..$ :List of 3
.. .. .. ..$ start: num 0.995
.. .. .. ..$ end : num 1.5
.. .. .. ..$ label: chr "limite"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.5
.. .. .. ..$ end : num 1.82
.. .. .. ..$ label: chr ""
..$ :List of 5
.. ..$ class : chr "IntervalTier"
.. ..$ name : chr "segments"
.. ..$ start : num 0
.. ..$ end : num 1.82
.. ..$ intervals:List of 8
.. .. ..$ :List of 3
.. .. .. ..$ start: num 0
.. .. .. ..$ end : num 0.995
.. .. .. ..$ label: chr ""
.. .. ..$ :List of 3
.. .. .. ..$ start: num 0.995
.. .. .. ..$ end : num 1.07
.. .. .. ..$ label: chr "l"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.07
.. .. .. ..$ end : num 1.15
.. .. .. ..$ label: chr "i"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.15
.. .. .. ..$ end : num 1.23
.. .. .. ..$ label: chr "m"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.23
.. .. .. ..$ end : num 1.28
.. .. .. ..$ label: chr "i"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.28
.. .. .. ..$ end : num 1.37
.. .. .. ..$ label: chr "t"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.37
.. .. .. ..$ end : num 1.5
.. .. .. ..$ label: chr "e"
.. .. ..$ :List of 3
.. .. .. ..$ start: num 1.5
.. .. .. ..$ end : num 1.82
.. .. .. ..$ label: chr ""
O usando, por ejemplo, tg$tiers[[tier_number]]$intervals[[interval_number]]
.