使用可变选择范围进行子集

时间:2013-09-26 19:03:02

标签: r for-loop subset sapply

我必须在这个数据集(dat)上做出一系列选择,这些选择由物种(sp),日(天,在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”的区域,在1-jan-00,我只需要区域1和6.对于2-jan-00,区域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)

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

您可以将条件表合并到原始数据集并有条件地过滤它们。考虑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

答案 1 :(得分:2)

首先,我不会使用as.data.frame(cbind(...))制作您的data.frame。其次,我会在你创建的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")