R 基于现有列及其旁边的列的新列
我的数据框看起来像这样R 基于现有列及其旁边的列的新列,r,dplyr,melt,R,Dplyr,Melt,我的数据框看起来像这样 ID t1 obs1 t2 obs2 t3 obs3 1 0 a 11 d 0 g 2 0 b 13 e 11 i 3 0 c 0 f 0 h 我需要确保每个ID至少有一个大于10的t(如果不是,请删除行)。然后,我想保存10以上的最低t值,但也要将相应的obs保存在新列中。(关于我的问题,最复杂的部分是,10以上的最低t可能在任何列中)。与某个t对应的obs位于下一列中,因此这会有所帮助。因此,我的结果数据框如下所
ID t1 obs1 t2 obs2 t3 obs3
1 0 a 11 d 0 g
2 0 b 13 e 11 i
3 0 c 0 f 0 h
我需要确保每个ID至少有一个大于10的t(如果不是,请删除行)。然后,我想保存10以上的最低t值,但也要将相应的obs保存在新列中。(关于我的问题,最复杂的部分是,10以上的最低t可能在任何列中)。与某个t对应的obs位于下一列中,因此这会有所帮助。因此,我的结果数据框如下所示:
ID t1 obs1 t2 obs2 t3 obs3 lowesttabove10 correspondingobs
1 0 a 11 d 0 g 11 d
2 0 b 13 e 11 i 11 i
我的方法不是很好,但仍然有效,你可以试试
library(dplyr)
library(reshape)
df1=melt(df,id='ID')
df2=df1%>%group_by(ID)%>%filter(value>10)%>%dplyr::slice(which.min(value))%>%na.omit()
> df2
# A tibble: 2 x 3
# Groups: ID [2]
ID variable value
<int> <fctr> <chr>
1 1 t2 11
2 2 t3 11
df2$variable=as.character(df2$variable)
C=as.numeric(gsub("[[:alpha:]]", "", df2$variable))
df=df[df$ID%in%df2$ID,]
for (i in 1:length(C)){
DF1=df[i,str_detect(names(df),as.character(C[i]))]
names(DF1)=c('lowesttabove10 ','correspondingobs')
if (i ==1 ){DFF=DF1}else{DFF=rbind(DFF,DF1)}
}
cbind(df,DFF)
ID t1 obs1 t2 obs2 t3 obs3 lowesttabove10 correspondingobs
1 1 0 a 11 d 0 g 11 d
2 2 0 b 13 e 11 i 11 i
库(dplyr)
图书馆(重塑)
df1=熔体(df,id='id')
df2=df1%%>%group_by(ID)%%>%filter(value>10)%%>%dplyr::slice(which.min(value))%%>%na.omit()
>df2
#一个tibble:2x3
#组别:ID[2]
ID变量值
1 1 t2 11
2 t3 11
df2$variable=as.character(df2$variable)
C=as.numeric(gsub(“[:alpha:][]”,“”,df2$变量))
df=df[df$ID%在%df2$ID中,]
适用于(i/1:长度(C)){
DF1=df[i,str_detect(名称(df),as.character(C[i]))
名称(DF1)=c('lowersttabove10','correspondingobs')
如果(i==1){DFF=DF1}否则{DFF=rbind(DFF,DF1)}
}
cbind(df,DFF)
ID t1 obs1 t2 obs2 t3 obs3下表10对应的obs2
11A11D 0G11D
2 2 0 b 13 e 11 i 11 i
解决方案在一个管道中使用dplyr
和tidyr
dt
是原始数据,dt2
是最终输出
library(dplyr)
library(tidyr)
dt2 <- dt %>%
gather(t_group, t_value, starts_with("t")) %>%
gather(obs_group, obs_value, starts_with("obs")) %>%
filter(gsub("t", "", t_group) == gsub("obs", "", obs_group)) %>%
filter(t_value >= 10) %>%
filter(t_value == min(t_value)) %>%
select(ID, lowesttabove10 = t_value, correspondingobs = obs_value) %>%
inner_join(dt, by = "ID") %>%
select(colnames(dt), lowesttabove10, correspondingobs)
df2
ID t1 obs1 t2 obs2 t3 obs3 lowesttabove10 correspondingobs
1 1 0 a 11 d 0 g 11 d
2 2 0 b 13 e 11 i 11 i
库(dplyr)
图书馆(tidyr)
dt2%
聚集(t_组,t_值,以(“t”)开头)%>%
聚集(obs_组,obs_值,以(“obs”)开头)%>%
过滤器(gsub(“t”),t_组)==gsub(“obs”,“obs”,obs_组))%>%
过滤器(t_值>=10)%>%
过滤器(t_值==最小值(t_值))%>%
选择(ID,最下选项卡10=t_值,对应的BS=obs_值)%>%
内部联接(dt,by=“ID”)%>%
选择(列名称(dt)、最下表10、对应的选项卡)
df2
ID t1 obs1 t2 obs2 t3 obs3下表10对应的obs2
11A11D 0G11D
2 2 0 b 13 e 11 i 11 i
数据:
dt使用基数R:
删除t值不超过10的所有行:
df1 <- df1[rowSums(df1[, grepl("^t", colnames(df1))] >10) > 0, ]
df1 10)>0,]
确定包含10以上最低值的组,然后检索值:
df1$group <- apply(df1[grepl("^t", names(df1))], 1, function(x) which(x == min(x[x > 10])))
df1 <- cbind(df1, do.call(rbind, lapply(seq_len(nrow(df1)),
function(x) setNames(df1[x, paste0(c("t", "obs"), df1$group[x])],
c("lowesttabove10", "correspondingobs")))))
> df1
ID t1 obs1 t2 obs2 t3 obs3 group lowesttabove10 correspondingobs
1 1 0 a 11 d 0 g 2 11 d
2 2 0 b 13 e 11 i 3 11 i
df1$group 10]))
df1 df1
ID t1 obs1 t2 obs2 t3 obs3 obs3组最下面的10个对应OBS
11A11D0G211D
2 2 0 b 13 e 11 i 3 11 i
对于data.table,转到长格式:
library(data.table)
setDT(DT)
dat = melt(DT, measure.vars = patterns("^t\\d+$", "^obs\\d+$"), value.name = c("t", "obs"))
setorder(dat, ID, variable)
# ID variable t obs
# 1: 1 1 0 a
# 2: 1 2 11 d
# 3: 1 3 0 g
# 4: 2 1 0 b
# 5: 2 2 13 e
# 6: 2 3 11 i
# 7: 3 1 0 c
# 8: 3 2 0 f
# 9: 3 3 0 h
查找每个组的最大值并标记要保留的组:
IDDT = dat[order(-t),
.(max.variable = first(variable), max.t = first(t), max.obs = first(obs))
, by=ID]
IDDT[, keep := max.t > 10]
# ID max.variable max.t max.obs keep
# 1: 2 2 13 e TRUE
# 2: 1 2 11 d TRUE
# 3: 3 1 0 c FALSE
使用滚动更新联接查找每个保留组超过10的最小值:
IDDT[(keep), c("my.variable", "my.t", "my.obs") := {
m = .(ID = ID, t_thresh = 10)
dat[m, on=.(ID, t = t_thresh), roll=-Inf, .(x.variable, x.t, x.obs)]
}]
# ID max.variable max.t max.obs keep my.variable my.t my.obs
# 1: 2 2 13 e TRUE 3 11 i
# 2: 1 2 11 d TRUE 2 11 d
# 3: 3 1 0 c FALSE NA NA NA
我就到此为止,主要数据是长格式的dat
,而ID
级别变量则在单独的表IDDT
中。要将dat
筛选到应保留的组:dat[IDDT[(保留),(ID)],on=(ID)]
。有关语法的详细信息,请参阅?data.table
和加载软件包时提到的其他介绍材料
如果您坚持要返回到广域,请参见?dcast
。重塑是为了更好地使用plyr而构建的,而tidyr是为了dplyr,仅供参考。刚刚注意:您需要将df1$值转换为数字。使用character,您将在过滤器内看到“2”>10
。另外,看起来您的第二步应该/可能是left_-join(df2,df)
?@Frank是的,您是对的,我这边的'1'>10
返回FALSE
您知道我为什么会出现此错误吗?错误:is_DictionarySh(x)不正确不确定。尝试获取最新的dplyr
或tidyverse
软件包。如果错误仍然发生,您可以使用base R或data.table
中的方法,如其他人建议的那样。
IDDT[(keep), c("my.variable", "my.t", "my.obs") := {
m = .(ID = ID, t_thresh = 10)
dat[m, on=.(ID, t = t_thresh), roll=-Inf, .(x.variable, x.t, x.obs)]
}]
# ID max.variable max.t max.obs keep my.variable my.t my.obs
# 1: 2 2 13 e TRUE 3 11 i
# 2: 1 2 11 d TRUE 2 11 d
# 3: 3 1 0 c FALSE NA NA NA