我是 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)
有一个名为的函数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)
要转换为百分比(假设您将持续时间表示为每个时间段的百分比),您可以除以原始测量次数,此处等于colSums。sweep可以使用函数 div 按行 (1) 或按列 (2) 应用值'/'。
sweep(tab, 2, colSums(tab), '/')
Run Code Online (Sandbox Code Playgroud)