R通过选定的rownumbers对数据帧进行动态拆分/子集 - 解析textgrid praat

时间:2014-02-20 21:23:18

标签: r data-structures split subset praat

我正在尝试处理名为.TextGrid的“分段文件”(由Praat程序生成)。 )

原始格式如下:

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]:
[...]

(然后将其重复为EOF,文件中n项(注释层)的间隔为[3到n]。

某人proposed a solution使用rPython R package

不幸的是:

  • 我对Python没有很好的了解
  • rPython的版本不适用于R.3.0.2 (我正在使用)。
  • 我的目标是在R环境下专门为我的分析开发此解析器。

现在我的目标是将此文件分割为多个数据框。每个数据框应包含一个项目(注释层)。

# 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)

head(txtgrid)的输出非常原始,所以这是textgrid txtgrid[1:20,]的前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 

现在我预先处理了它,我可以:

# 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))

这个变量x给我数字-1,我的数据应该在几个数据帧中分割。

我有18个项目-1(第一个项目是项目[]并包含所有其他项目。所以向量x是:

     x
    [1]     7     8 10034 14624 19214 22444 25674 28904 31910 35140 38146 38156 38566 39040 39778 40222 44800
[18] 45018

如何告诉R :在多个数据框textgrids$nameoftheItem中对此数据帧进行细分,以便获得与项目数量相同的数据框?例如:

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]

我想用

txtgrid.new <- split(txtgrid, f=x)

但是这条消息是正确的:

Warning message: In split.default(x = seq_len(nrow(x)), f = f, drop = drop, ...) : data length is not a multiple of split variable

我没有得到理想的输出,似乎行号不会互相跟随,并且文件全部混淆。

我还尝试了一些whichdaply(来自plyr)&amp; subset功能,但从未使它们正常工作!

我欢迎任何想法正确地构建这些数据&amp;有效率的。理想情况下,我应该能够链接它们之间的项目(注释层)(不同层的xmin和xmax),以及多个textgrid文件,这只是一个开始。

2 个答案:

答案 0 :(得分:2)

split向量的长度应等于data.frame中的行数。

尝试以下方法:

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))

修改

然后您可以通过执行以下操作来简化数据:

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>

注意:我已经使用了虚假数据。

答案 1 :(得分:0)

你似乎在其他地方找到了一个很好的解决方案,但我想我不妨把它放在这里作为参考:

我最近完成了可用于此的Praat对象的JSON转换器的第一个工作版本。您可以使用this plugin中包含的脚本save_as_json.praat将TextGrid另存为JSON文件(同样:我是该插件的作者)。

this other answer复制到类似的问题,一旦安装了插件,您就可以使用Praat中Save菜单中的脚本,或者从另一个脚本中运行它:

runScript: preferencesDirectory$ + "/plugin_jjatools/save_as_json.praat",
  ..."/output/path", "Pretty printed" 

完成后,您可以使用R将其读入rjson,如下所示:

> 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 ""

或者使用,例如tg$tiers[[tier_number]]$intervals[[interval_number]]