基于向量条件的子集数据帧

时间:2014-02-18 14:20:16

标签: r dataframe subset

我有两个数据帧

#df1
type <- c("A", "B", "C")
day_start <- c(5,8,4)
day_end <- c(12,10,11)
df1 <- cbind.data.frame(type, day_start, day_end)
df1
  type day_start day_end
1    A         5      12
2    B         8      10
3    C         4      11

#df2
value <- 1:10
day <- 4:13
df2 <- cbind.data.frame(day, value)
   day value
1    4     1
2    5     2
3    6     3
4    7     4
5    8     5
6    9     6
7   10     7
8   11     8
9   12     9
10  13    10

我想将df2子集化,使df1中每个级别的因子“type”获得自己的数据帧,仅包括此因子级别的day_start和day_end之间的行/天。

“A”的期望结果将是..

list_of_dataframes$df_A
   day value
1    5     2
2    6     3
3    7     4
4    8     5
5    9     6
6   10     7
7   11     8
8   12     9

我在SO上找到了this question,答案建议使用mapply(),但是,我只是无法弄清楚如何调整那里的代码以适应我的数据和期望的结果..有人可以帮助我出去了吗?

2 个答案:

答案 0 :(得分:3)

以下解决方案假设你有几天的所有整数值,但如果这个假设是合理的,那么这是一个简单的单行:

> apply(df1, 1, function(x) df2[df2$day %in% x[2]:x[3],])
[[1]]
  day value
2   5     2
3   6     3
4   7     4
5   8     5
6   9     6
7  10     7
8  11     8
9  12     9

[[2]]
  day value
5   8     5
6   9     6
7  10     7

[[3]]
  day value
1   4     1
2   5     2
3   6     3
4   7     4
5   8     5
6   9     6
7  10     7
8  11     8

您可以使用setNames命名列表中的数据框:

setNames(apply(df1, 1, function(x) df2[df2$day %in% x[2]:x[3],]),df1[,1])

答案 1 :(得分:2)

是的,您可以使用mapply

定义一个能完成你想要的功能:

fun <- function(x,y) df2[df2$day >= x & df2$day <= y,]

然后使用mapply将此功能应用于day_startday_end的每个元素:

final.output <- mapply(fun,df1$day_start, df1$day_end, SIMPLIFY=FALSE)

这将为您提供包含所需输出的列表:

final.output

[[1]]
  day value
2   5     2
3   6     3
4   7     4
5   8     5
6   9     6
7  10     7
8  11     8
9  12     9

[[2]]
  day value
5   8     5
6   9     6
7  10     7

[[3]]
  day value
1   4     1
2   5     2
3   6     3
4   7     4
5   8     5
6   9     6
7  10     7
8  11     8

您可以使用data.frame

为列表中的每个setNames命名
final.output <- setNames(final.output,df1$type)

或者您也可以在列表的data.frames上添加属性类型:

fun <- function(x,y, type){
  df <- df2[df2$day >= x & df2$day <= y,]
  attr(df, "type") <- as.character(type)
  df
}

然后data.frame的每个final.output都会有一个属性,因此您知道它是哪种类型:

final.output <- mapply(fun,df1$day_start, df1$day_end,df1$type, SIMPLIFY=FALSE)

# check wich type the first data.frame is 
attr(final.output[[1]], "type")
[1] "A"

最后,如果您不想要包含3 data.frames的列表,您可以创建一个将3个data.frames分配给全局环境的函数:

fun <- function(x,y, type){
  df <- df2[df2$day >= x & df2$day <= y,]
  name <- as.character(type)
  assign(name, df, pos=.GlobalEnv)
}

mapply(fun,df1$day_start, df1$day_end, type=df1$type, SIMPLIFY=FALSE)

这将在名为A,B和C的全局环境中创建3个独立的data.frame。