在 R 中循环遍历列并找到第一个值等于 1

Loop in R through columns and find the first value equal 1

我想遍历数据框中的列(从左到右)并找到每行中第一个等于 1 的值。如果该值等于 1,那么我想向名为 x_time = 9,10,11,12 或 13 的数据框中添加一个新列,具体取决于首先找到值 1 的时间点。

查看数据示例

df <- data.frame(x9 = c('', '', 2, '', 1, ''),
                 x10 = c('', 1, '', '', '', ''),
                 x11 = c('', '', 2, '', 1, ''),
                 x12 = c(1, 1, 2, '', '', ''),
                 x13 = c('', '', 2, '', 2, ''))
                
Desired output:

  x9 x10 x11 x12 x13 x_time
1        1       12
2    1     1       10
3  2     2   2   2     NA
4              NA
5  1     1     2      9
6              NA

请告诉我什么是最有效的方法。

在 Stata 中,我会制作一个全局宏并循环遍历其内容:

global varlist “x09 x10 x11 x12 x13” 
gen x_time = .
foreach var in $varlist {
    replace x_time = substr("`var'",-2,.) if x_time == . & `var' == 1
}

你可以这样循环出去

vec <- c()
for (k in 1:nrow(df)) {
  if(length(which(as.vector(unlist(df[k,]))=="1"))>0){
    vec[k] <- as.numeric(gsub("x","",colnames(df)[which(as.vector(unlist(df[k,]))=="1")[1]]))
      
  }else{
    vec[k] <- NA
  }
  
}

df$x_time <- vec

输出

> df
  x9 x10 x11 x12 x13 x_time
1        1       12
2    1     1       10
3  2     2   2   2     NA
4              NA
5  1     1     2      9
6              NA

这是一个data.table方法

library(data.table)
# Convert to data.table, keep rownames as identifier
setDT(df, keep.rownames = TRUE)
# join molten data on df
df[melt(df, id.vars = "rn")[value == 1, .SD[1], by = .(rn)],
   x_time := gsub("x", "", i.variable),
   on = .(rn)]
#    rn x9 x10 x11 x12 x13 x_time
# 1:  1        1       12
# 2:  2    1     1       10
# 3:  3  2     2   2   2   <NA>
# 4:  4            <NA>
# 5:  5  1     1     2      9
# 6:  6            <NA>

这是一个tidyverse方法:

  1. 如果列为 1,则连接列名。
  2. 当我们用 1 搜索第一列时,我们可以使用 parse_number 从字符串中选择第一个数字!
library(dplyr)
library(tidyr)

df %>% 
  mutate(across(x9:x13, ~case_when(. == "1" ~ cur_column()), .names = 'new_{col}')) %>%
  unite(New_Col, starts_with('new'), na.rm = TRUE, sep = ' ') %>% 
  mutate(x_time=parse_number(New_Col), .keep="unused")

输出:

  x9 x10 x11 x12 x13 x_time
1        1       12
2    1     1       10
3  2     2   2   2     NA
4              NA
5  1     1     2      9
6              NA