如何计算元素在时间步 t 出现的总次数?

use*_*708 5 r dataframe

我是 R 的初学者,但我想编写一段需要一些 R 和数据科学知识的代码。

我有一个具有以下结构的数据框;t1 表示 10 分钟时间段,1 定义测量值。

 t1 t2 t3 t4
  1  0  0  0
  1  1  1  1
  0  1  1  1
  0  1  1  1
  1  0  1  1
Run Code Online (Sandbox Code Playgroud)

我想确定每次测量的持续时间和起点。例如,有两个 10 分钟的测量从 t1(第 1 行和第 5 行)开始,有两个 30 分钟的测量从 t2(第 3 行和第 4 行)开始。

输出:

 duration_minutes   t1 t2 t3 t4
      10            2   0  0  0
      20            1   0  1  0
      30            0   2  0  0
      40            1   0  0  0
Run Code Online (Sandbox Code Playgroud)

有没有办法将计数转换为百分比?

df<-structure(list(t1 = c(1, 1, 0, 0,1),
                   t2 = c(0, 1, 1, 1,0), t3 = c(0, 1, 1, 1,1), t4 = c(0, 1, 1,  1,1)), row.names = c(NA,5L), class = "data.frame") 

                                                                                  
Run Code Online (Sandbox Code Playgroud)

nni*_*loc 2

有一个名为的函数rle似乎很适合这里。这个答案几乎都是baseR,但我还是忍不住深入研究了tidyversefor map_dfr

library(purrr)

df_rle <- map_dfr(row.names(df), function(x){
  r <- rle(rev(df[x,]))
  rev(r$lengths * r$values * 10)  
})

tab <- table(stack(df_rle), exclude = c('0', NA))
tab
#---------
      ind
values t1 t2 t3
    10  2  0  0
    20  0  0  1
    30  0  2  0
    40  1  0  0
Run Code Online (Sandbox Code Playgroud)

如果您想将这些表示为百分比

sweep(tab,2, colSums(tab), '/')

#--------
      ind
values        t1        t2        t3
    10 0.6666667 0.0000000 0.0000000
    20 0.0000000 0.0000000 1.0000000
    30 0.0000000 1.0000000 0.0000000
    40 0.3333333 0.0000000 0.0000000

Run Code Online (Sandbox Code Playgroud)

稍微分解一下

当该rle函数在给定行上运行时,我们非常接近所需的输出。作为示例,来自 的第 5 行df

r <- rle(c(1,0,1,1))
r
#-----
Run Length Encoding
  lengths: int [1:3] 1 1 2
  values : num [1:3] 1 0 1


# Multiply to get time periods
r$lengths * r$values * 10
# -----
[1] 10  0 20
Run Code Online (Sandbox Code Playgroud)

但是,以数据帧行作为输入,值将链接到最后一个时间段而不是第一个时间段。因此,我们反转将行提供给函数的顺序rle,然后取消反转(?)结果。

r <- rle(df[5,])
r$values
#------
  t1 t2 t4
5  1  0  1

# Reverse before we feed into rle(), reverse the output
r <- rle(rev(df[5,]))
rev(r$lengths * r$values * 10) 
#-----------
  t1 t2 t3
5 10  0 20
Run Code Online (Sandbox Code Playgroud)

然后我们需要对每一行执行这个反向 rle 函数。这个答案使用purrr::map_dfr(),它将函数映射到每一行,然后 row 将结果绑定到一个数据帧中。

df_rle <- map_dfr(row.names(df), function(x){
  r <- rle(rev(df[x,]))
  rev(r$lengths * r$values * 10)  
}) 


#-----
  t1 t2 t3
1 10  0 NA
2 40 NA NA
3  0 30 NA
4  0 30 NA
5 10  0 20

Run Code Online (Sandbox Code Playgroud)

从这里开始,我们需要按 10 分钟持续时间类别来计算值。做这件事有很多种方法。df_rle这是我们首先使用 转换为长格式两列数据帧stack,然后使用该table函数按持续时间级别进行制表的一种方法。

tab <- table(stack(df_rle), exclude = c('0', NA))

#--------
      ind
values t1 t2 t3
    10  2  0  0
    20  0  0  1
    30  0  2  0
    40  1  0  0
Run Code Online (Sandbox Code Playgroud)

要转换为百分比(假设您将持续时间表示为每个时间段的百分比),您可以除以原始测量次数,此处等于colSumssweep可以使用函数 div 按行 (1) 或按列 (2) 应用值'/'

sweep(tab, 2, colSums(tab), '/')
Run Code Online (Sandbox Code Playgroud)