【问题标题】:Loop in R through columns and find the first value equal 1在 R 中循环遍历列并找到第一个等于 1 的值
【发布时间】:2021-12-17 00:10:55
【问题描述】:

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

查看数据示例

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

  x9 x10 x11 x12 x13 x_time
1 $7  $7  $7   1  $7     12
2 $7   1  $7   1  $7     10
3  2  $7   2   2   2     NA
4 $7  $7  $7  $7  $7     NA
5  1  $7   1  $7   2      9
6 $7  $7  $7  $7  $7     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
}

【问题讨论】:

  • 您必须编辑您的 df 和所需的输出。第三行不正确。
  • 我做了,谢谢指出。
  • 顺便说一句,您在 Stata 中使用全局宏既不是必要的,也不是好的做法。只是循环 foreach var in x09 x10 x11 x12 x13 将是其他几种解决方案之一。

标签: r dataframe loops stata


【解决方案1】:

这是tidyverse 方法:

  1. 如果colum 为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 $7  $7  $7   1  $7     12
2 $7   1  $7   1  $7     10
3  2  $7   2   2   2     NA
4 $7  $7  $7  $7  $7     NA
5  1  $7   1  $7   2      9
6 $7  $7  $7  $7  $7     NA

【讨论】:

    【解决方案2】:

    这是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 $7  $7  $7   1  $7     12
    # 2:  2 $7   1  $7   1  $7     10
    # 3:  3  2  $7   2   2   2   <NA>
    # 4:  4 $7  $7  $7  $7  $7   <NA>
    # 5:  5  1  $7   1  $7   2      9
    # 6:  6 $7  $7  $7  $7  $7   <NA>
    

    【讨论】:

      【解决方案3】:

      你可以这样循环出去

      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 $7  $7  $7   1  $7     12
      2 $7   1  $7   1  $7     10
      3  2  $7   2   2   2     NA
      4 $7  $7  $7  $7  $7     NA
      5  1  $7   1  $7   2      9
      6 $7  $7  $7  $7  $7     NA
      

      【讨论】:

      • 这是一个合乎逻辑且类似于 Stata 的方法,我可以轻松掌握。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 1970-01-01
      • 2010-12-09
      • 2015-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多