【问题标题】:Subsetting with variable selection range具有可变选择范围的子集
【发布时间】:2013-09-26 19:03:02
【问题描述】:

我必须在这个数据集 (dat) 上做出一组随天而变的选择,该数据集由物种 (sp)、天 (day, in POSIXct) 和面积 (ar) 组成:

sp  day         ar
A   1-Jan-00    2
B   1-Jan-00    6
C   2-Jan-00    2
A   2-Jan-00    1
D   2-Jan-00    4
E   2-Jan-00    12
F   3-Jan-00    8
A   4-Jan-00    3
G   4-Jan-00    2
B   4-Jan-00    1

我需要对物种“A”出现的位置进行子集化。但是,要选择的区域会因天而异,由该矩阵 (dat.ar) 给出:

day       ar.select
1-Jan-00    (1,6)
2-Jan-00    (1,12)
3-Jan-00    (4,8)
4-Jan-00    (3,12)

更具体地说,对于物种“A”出现的区域,在 00 年 1 月 1 日,我只需要区域 1 和 6。对于 00 年 1 月 2 日,区域 1 和 12,依此类推。 作为示例,此示例的此选择所需的输出如下所示:

sp  day        ar
A   2-Jan-00    1
A   4-Jan-00    3

我在获得 for 循环方面没有取得多大成功,因为我仍在尝试学习 R 中的语义。总而言之,大致了解了必须做什么,但仍在努力学习该语言。这是我认为应该去哪里的草图:

dat1 = with(dat,sapply(day[sp=="A" & dat.ar$day.s[i] ], 
function(x) ar == (ar[sp=="A" & day == x]==dat.ar$ar.select[j]) 
final=dat[rowSums(dat1) > 0, ]

我相信我必须安装一个 for 循环,它会通过 dat.ar,指定要在 dat 中选择的区域。但是,尽管我努力尝试 for 循环,但我还没有接近。我什至不确定结合 sapply 和 for 循环是否是解决此问题的正确方法。 如果有人希望重现该问题:

sp=c("A","B","C","A","D","E","F","A","G","B")
day=c("1-Jan-00", "1-Jan-00", "2-Jan-00", "2-Jan-00", "2-Jan-00", 
"2-Jan-00", "3-Jan-00", "4-Jan-00", "4-Jan-00", "4-Jan-00")
day=as.POSIXct(day, format="%d-%b-%y")
ar=c(2,6,2,1,4,12,8,3,2,1)
dat= as.data.frame(cbind(sp, day, ar)) 

day.s=c("1-Jan-00", "2-Jan-00", "3-Jan-00", "4-jan-00")
day.s=as.POSIXct(day.s, format="%d-%b-%y")
a.s=c(1,1,4,3)
a.e=c(6,12,8,12)
ar.select=paste(a.s, a.e, sep=",")
dat.ar=cbind(day.s, ar.select)

非常感谢任何帮助。

【问题讨论】:

    标签: r for-loop subset sapply


    【解决方案1】:

    您可以将条件表合并到原始数据集并有条件地过滤它们。将 a1 和 a2 视为您的 sp 和 day 值,将 obs 视为您的 ar 值。

    library(data.table)
    dataset <- data.table(
    a1 = c("A","B","C","B","A","A","A","A"),
    a2 = c("P","Q","Q","Q","R","R","P","Q"),
    obs = c(3,2,3,4,2,4,8,0)
    )
    
    constraints <- data.table(
    a1 = c("A","B","C","A","B","C","A","B","C"),
    a2 = c("P","P","P","Q","Q","Q","R","R","R"),
    lower = c(1,2,3,4,3,2,3,2,5),
    upper = c(6,4,5,7,5,6,5,3,7)
    )
    
    
    checkingdataset <- merge(dataset,constraints, by = c("a1","a2"), all.x = TRUE)
    
    checkingdataset[obs <= upper & obs >= lower, obs.keep := TRUE]
    
    
    #   a1 a2 obs lower upper obs.keep
    #1:  A  P   3     1     6    TRUE
    #2:  A  P   8     1     6      NA
    #3:  A  Q   0     4     7      NA
    #4:  A  R   2     3     5      NA
    #5:  A  R   4     3     5    TRUE
    #6:  B  Q   2     3     5      NA
    #7:  B  Q   4     3     5    TRUE
    #8:  C  Q   3     2     6    TRUE
    

    【讨论】:

      【解决方案2】:

      首先,我不会使用as.data.frame(cbind(...)) 来制作您的data.frames。其次,我将创建dat.ar,其结构与您创建dat 的结构大致相同。第三,然后我会使用 merge 来获得您正在寻找的结果。

      dat <- data.frame(sp=c("A","B","C","A","D","E","F","A","G","B"),
                        day=c("1-Jan-00", "1-Jan-00", "2-Jan-00", "2-Jan-00", 
                              "2-Jan-00", "2-Jan-00", "3-Jan-00", "4-Jan-00", 
                              "4-Jan-00", "4-Jan-00"),
                        ar=c(2,6,2,1,4,12,8,3,2,1))
      dat$day <- as.POSIXct(dat$day, format="%d-%b-%y")
      
      day.s <- c("1-Jan-00", "2-Jan-00", "3-Jan-00", "4-jan-00")
      day.s <- as.POSIXct(day.s, format="%d-%b-%y")
      a.s <- c(1,1,4,3)
      a.e <- c(6,12,8,12)
      ar.select <- paste(a.s, a.e, sep=",")
      dat.ar <- data.frame(sp = "A", day = day.s, ar = ar.select)
      
      dat.ar <- cbind(dat.ar[-3], 
                      read.csv(text = as.character(dat.ar$ar), header = FALSE))
      library(reshape2)
      dat.ar <- melt(dat.ar, id.vars=1:2, value.name="ar")
      dat.ar
      #   sp        day variable ar
      # 1  A 2000-01-01       V1  1
      # 2  A 2000-01-02       V1  1
      # 3  A 2000-01-03       V1  4
      # 4  A 2000-01-04       V1  3
      # 5  A 2000-01-01       V2  6
      # 6  A 2000-01-02       V2 12
      # 7  A 2000-01-03       V2  8
      # 8  A 2000-01-04       V2 12
      
      merge(dat, dat.ar)
      #   sp        day ar variable
      # 1  A 2000-01-02  1       V1
      # 2  A 2000-01-04  3       V1
      

      当然,我只是建议您一开始就以更友好的方式创建您的 dat.ar 对象。如果您稍后要将它们分开,为什么还要将它们粘贴在一起? ;)

      dat.ar <- data.frame(sp = "A", 
                           day = c("1-Jan-00", "2-Jan-00", "3-Jan-00", "4-jan-00"),
                           a.s = c(1,1,4,3), a.e = c(6,12,8,12))
      dat.ar$day <- as.POSIXct(dat.ar$day, format="%d-%b-%y")
      
      library(reshape2)
      dat.ar <- melt(dat.ar, id.vars=1:2, value.name="ar")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-18
        • 1970-01-01
        • 2012-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-15
        • 1970-01-01
        相关资源
        最近更新 更多