r-使用非标准间接引用的函数



我需要一个函数f(B,a(,给定一个具有以下结构的数据集,

T1 T2 T3 T4 T5  ... P1 P2 P3 P4 P5 ...
1  2  5  8  9  ...  A  C  B  B  A ... 
1  3  4  6  6  ...  C  A  C  A  B ...

找到Pj列中出现的第一个时间B和A(从j=1开始(,并返回相应Ti列中的值差。例如:

第1行中的
  • :B首先出现在P3中,A首先出现在P1中。然后:

f(B,A(=T3-T1=5-1=4

  • 第2行:B首先出现在P5中,A首先出现在P2中。然后:

f(B,A(=T5-T2=6-3=3

我可以使用str_detect((找到Pj列B和A出现在其中,但我不知道如何"移动";从P_j1,P_j2到T_j1,T_j2。

使用数据表语法(或基本R(将受到的赞赏

这里有一个data.table方法。

library(data.table)
DT <- fread("T1 T2 T3 T4 T5  P1 P2 P3 P4 P5
1  2  5  8  9   A  C  B  B  A 
1  3  4  6  6   C  A  C  A  B")
# Add row ID's
DT[, id := .I]
#melt to a long format
DT.melt <- data.table::melt(DT, 
id.vars = "id",
measure.vars = patterns(T = "^T", P = "^P"))
# Find first B for each id
val1 <- DT.melt[P == "B", T[1], by = .(id)]$V1
# [1] 5 6
# Find first A for each id
val2 <- DT.melt[P == "A", T[1], by = .(id)]$V1
# [1] 1 3
val1 - val2
# [1] 4 3

基R

f <- function(l1, l2){
apply(df, 1, function(x){
dfP <- x[grepl("P", names(x))]
dfT <- x[grepl("T", names(x))]

as.numeric(dfT[which(dfP == l1)[1]]) - as.numeric(dfT[which(dfP == l2)[1]])
})
}
f("B", "A")
[1] 4 3

Tidyverse

对于这种类型的数据,通常最好先转向长,然后再转向宽:这里是tidyverse解决方案,diff是所需的输出。

library(tidyverse)
df %>% 
mutate(id = row_number()) %>% 
pivot_longer(-id, names_pattern = "(\D)(\d)", 
names_to = c(".value", "group")) %>% 
group_by(id) %>% 
mutate(diff = first(T[P == "B"]) - first(T[P == "A"])) %>% 
pivot_wider(c(id, diff), names_from = group, values_from = c(T, P), names_sep = "")

输出

id  diff    T1    T2    T3    T4    T5 P1    P2    P3    P4    P5   
<int> <int> <int> <int> <int> <int> <int> <chr> <chr> <chr> <chr> <chr>
1     1     4     1     2     5     8     9 A     C     B     B     A    
2     2     3     1     3     4     6     6 C     A     C     A     B  

最新更新