根据条件标志将列名转换为行值

Converting column names to row values based on conditional flags

我正在处理具有不同 body 部分和放射学测试列的医疗保健数据。下面是数据框的快照 -

 loc_brain  loc_bone  loc_pelvis  mod_ct  mod_xray
   0          1          1          0        1
   1          1          0          1        0
   0          0          1          1        1
  1. 所有以 "loc" 开头的列都标记了 body 部分。同样,以 "mod" 开头的列标记放射学测试

  2. 我们的想法是创建两个新的列,称为位置和模态,它们应遵循以下输出模式

    loc_brain  loc_bone  loc_pelvis  mod_ct  mod_xray  location            modality
      0          1          1          0        1      bone pelvis         xray
      1          1          1          1        1      brain bone pelvis   ct xray
      0          0          1          1        1      pelvis              ct xray
    

如果 "loc" 列标记为 1,则新位置列将具有 body 部分的名称。同样适用于 "mod" 列。

我解决这个问题的方法是使用 dplyr 并查看每个组合标志并填充位置和模态值。

input_df$location<-""  
input_df$modality<-""  
input_df <- input_df %>%  
            mutate(location= replace(location,(loc_bone==1 & loc_pelvis==1),"bone pelvis")) %>%  
            mutate(modality= replace(modality,mod_xray==1, "xray"))
  1. body 部分和测试大约有百万行和 65 列。
  2. 找到所有组合并对每个组合进行变异是一件很麻烦的事情。有没有办法使用 dplyr 或 base R 来自动化这种方法?

下面是输入数据框的可重现示例 -

loc_brain<-c(0,1,0)  
loc_bone<-c(1,1,0)  
loc_pelvis<-c(1,0,1)
mod_ct<-c(0,1,1)  
mod_xray<-c(1,0,1)  
input_df<-as.data.frame(cbind(loc_brain,loc_bone,loc_pelvis,mod_ct,mod_xray))

data.table的可能解决方案:

library(data.table)
setDT(input_df)[, loc := paste0(gsub('loc_','',names(.SD)[.SD==1]), collapse = ' '), 1:nrow(input_df), .SDcols = 1:3
                ][, mod := paste0(gsub('mod_','',names(.SD)[.SD==1]), collapse = ' '), 1:nrow(input_df), .SDcols = 4:5][]

给出:

   loc_brain loc_bone loc_pelvis mod_ct mod_xray         loc     mod
1:         0        1          1      0        1 bone pelvis    xray
2:         1        1          0      1        0  brain bone      ct
3:         0        0          1      1        1      pelvis ct xray

这是一种可行的方法,尽管我不确定它的通用性如何。

首先获取 "location" 列的列引用,然后使用它来仅提取 "location" 值("bone"、"brian" 等)。

location.columns <- grep( "^loc_", names(df) )

location.values <- names( df )[ location.columns ]
location.values <- sub( "^loc_", "", location.values )

然后从主数据框中分离出位置列,并用它来创建新列。我们在paste函数中使用collapse将各种匹配词粘在一起:

locations.df <- df[ , location.columns ]
df$location <- sapply( seq_len( nrow( df ) ),
                       function(x) {
                           paste( location.values[ locations.df[x,] == 1 ], collapse = " " )
                       }
)

对 "mod" 值重复这些步骤:

mod.columns <- grep( "^mod_", names(df) )

mod.values <- names( df )[ mod.columns ]
mod.values <- sub( "^mod_", "", mod.values )

mods.df <- df[ , mod.columns ]
df$mod <- sapply( seq_len( nrow( df ) ),
                       function(x) {
                           paste( mod.values[ mods.df[x,] == 1 ], collapse = " " )
                       }
)

给出:

> df
  loc_brain loc_bone loc_pelvis mod_ct mod_xray    location     mod
1         0        1          1      0        1 bone pelvis    xray
2         1        1          0      1        0  brain bone      ct
3         0        0          1      1        1      pelvis ct xray