【问题标题】:Find interval over similar column names in R在 R 中查找相似列名的区间
【发布时间】:2017-08-09 02:00:17
【问题描述】:

我想要一种更简单的方法来确定一个值是否在任何给定的区间内。给定数据框:

Value  start1  start2  start3  end1  end2  end3
212    82      195     409     97    220   411
80     57      95      111     69    100   130

如果“值”在任何区间([start1-end1]、[start2-end2] 等)中,我想创建一个 1 的新列,如果不是,则创建一个 0;因此在上述情况下,第一行的值为 1,因为 212 落在第二个间隔中,第二行为 0。请注意,这些是当前列和边缘情况的顺序(值匹配开始或间隔结束)应编码为 1。

我可以使用 ifelse 语句来做到这一点,但有 260 列,我觉得该解决方案将来可能会在其他方面有用。

【问题讨论】:

    标签: r dataframe intervals


    【解决方案1】:

    使用data.table 包:

    library(data.table)
    
    dt = data.table(Value=c(212,80), start1=c(82,57), start2=c(195,95), start3=c(409,111),
                    end1=c(97,69), end2=c(220,100), end3=c(411,130))
    
    dt[, rowid:= .I]
    

    使用“融化”的桌子更自然:

    dt_melt = melt(dt, id=c('rowid','Value'), measure=patterns('start','end'),
                   variable.name='interval', value.name=c('start','end'))
    
    #    rowid Value interval start end
    # 1:     1   212        1    82  97
    # 2:     2    80        1    57  69
    # 3:     1   212        2   195 220
    # 4:     2    80        2    95 100
    # 5:     1   212        3   409 411
    # 6:     2    80        3   111 130
    

    现在我们可以进行计算并与 rowid 上的dt 合并:

    dt[dt_melt[, as.integer(any(between(Value, start, end))), by='rowid'], on='rowid']
    
    #    Value start1 start2 start3 end1 end2 end3 rowid V1
    # 1:   212     82    195    409   97  220  411     1  1
    # 2:    80     57     95    111   69  100  130     2  0
    

    【讨论】:

    • 除了data.table还有什么我需要的,上面说没有叫做'patterns'的函数吗?
    • 不,模式来自 data.table。你用的是什么版本
    • 没关系,需要从data.frame转换为data.table
    • 谢谢你,我应该知道融化数据哈哈。这也将解决我的许多其他问题!
    【解决方案2】:

    使用tidyverse 的解决方案。最终输出在dt3 数据框的InRange 列中。

    # Create example data frame
    dt <- read.table(text = "Value  start1  start2  start3  end1  end2  end3
    212    82      195     409     97    220   411
                     80     57      95      111     69    100   130",
                     header = TRUE, stringsAsFactors = FALSE)
    
    # Load packages
    library(tidyverse)
    
    # Process the data
    dt2 <- dt %>% mutate(GroupID = 1:n()) 
    
    dt3 <- dt2 %>%
      gather(StartEnd, Number, -Value, -GroupID) %>%
      mutate(Type = gsub("[0-9]", "", StartEnd),
             ID = gsub("[a-z]", "", StartEnd)) %>%
      select(-StartEnd) %>%
      spread(Type, Number) %>%
      mutate(InRange = ifelse(Value >= start & Value <= end, 1, 0)) %>%
      group_by(GroupID) %>%
      summarise(InRange = max(InRange)) %>%
      right_join(dt2, by = "GroupID")
    

    请注意,我创建了GroupID 列以确保Value 列中的重复值(如果有)不会影响分析。但是,如果您确定没有重复值,则可以使用以下代码,而无需创建 GroupID 列。 dt2 是最终输出。

    # Process the data
    dt2 <- dt %>%
      gather(StartEnd, Number, -Value) %>%
      mutate(Type = gsub("[0-9]", "", StartEnd),
             ID = gsub("[a-z]", "", StartEnd)) %>%
      select(-StartEnd) %>%
      spread(Type, Number) %>%
      mutate(InRange = ifelse(Value >= start & Value <= end, 1, 0)) %>%
      group_by(Value) %>%
      summarise(InRange = max(InRange)) %>%
      right_join(dt, by = "Value") 
    

    【讨论】:

      猜你喜欢
      • 2021-08-31
      • 2016-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-10
      • 2011-03-09
      • 2017-04-25
      • 1970-01-01
      相关资源
      最近更新 更多