基于区间范围创建指标数据框

时间:2013-11-27 18:57:31

标签: r dataframe reshape2

我正在尝试从R中一个非常特殊类型的“宽”数据框中创建一个“长”数据框的指标(“虚拟”)变量,这些数据框的间隔范围为年定义我的数据。

我看起来像这样:

f=data.frame(name=c("A","B","C"),
             year.start=c(1990,1994,1993),year.end=c(1994,1995,1993))

  name year.start year.end
1    A       1990     1994
2    B       1994     1995
3    C       1993     1993

更新:我已经从1993年的初始示例更改了A到1990的year.start的值,以解决下面的一些依赖于唯一值而不是间隔的答案。

我想要的是一个看起来像这样的长数据框,其中包含原始数据框中每个可能年份的条目,例如1990 1995,其中1 =存在且0 =缺席。

 name year indicator
A     1990   1
A     1991   1
A     1992   1
A     1993   1
A     1994   1
A     1995   0
B     1990   0
B     1991   0
B     1992   0
B     1993   0
B     1994   1
B     1995   1
C     1990   0
C     1991   0
C     1992   0
C     1993   1
C     1994   0
C     1995   0

尽我所能,我不知道如何使用Hadley Wickham的reshape2包来做到这一点。

谢谢!

4 个答案:

答案 0 :(得分:3)

其他人可能会对reshape2提出建议,但这里有一个基本的R解决方案:

years <- factor(unlist(f[-1]), levels=seq(min(f[-1]), max(f[-1]), by=1))
result <- data.frame(table(years, rep(f[[1]], length.out=length(years))))
#    years Var2 Freq
# 1   1990    A    1
# 2   1991    A    0
# 3   1992    A    0
# 4   1993    A    0
# 5   1994    A    1
# 6   1995    A    0
# 7   1990    B    0
# 8   1991    B    0
# 9   1992    B    0
# 10  1993    B    0
# 11  1994    B    1
# 12  1995    B    1
# 13  1990    C    0
# 14  1991    C    0
# 15  1992    C    0
# 16  1993    C    2
# 17  1994    C    0
# 18  1995    C    0

答案 1 :(得分:2)

这是一个使用data.table

的逐步细分
library(data.table)
f <- as.data.table(f)

## ALL OF NAME-YEAR COMBINATIONS
ALL <- f[, CJ(name=name, year=seq(min(year.start), max(year.end)))]

## WHICH COMBINATIONS EXIST
PRESENT <- f[, list(year = seq(year.start, year.end)), by=name]

## SETKEYS FOR MERGING
setkey(ALL, name, year)
setkey(PRESENT, name, year)

## INITIALIZE INDICATOR TO ZERO, THEN SET TO 1 FOR THOSE PRESENT
ALL[, indicator := 0]
ALL[PRESENT, indicator := 1]

ALL

   name year indicator
1:    A 1993         1
2:    A 1994         1
3:    A 1995         0
4:    B 1993         0
5:    B 1994         1
6:    B 1995         1
7:    C 1993         1
8:    C 1994         0
9:    C 1995         0

答案 2 :(得分:1)

这是另一种类似于上述解决方案的解决方案,旨在直截了当:

zz           <- cbind(name=f[1],year=rep(min(f[-1]):max(f[-1]),each=nrow(f)))
zz$indicator <- as.numeric((f$name==zz$name & 
                            f$year.start<=zz$year & 
                            f$year.end  >=zz$year))
result       <- zz[order(zz$name,zz$year),]

第一行构建一个包含所有名称和所有年份的模板。第二行根据它是否存在于范围内来设置indicator。第三行只是重新排序结果。

答案 3 :(得分:0)

另一个基础R解决方案

f=data.frame(name=c("A","B","C"),
         year.start=c(1993,1994,1993),year.end=c(1994,1995,1993), stringsAsFactors=F)
x <- expand.grid(unique(f$name),min(f1$year):max(f1$year)) 
names(x) <- c("name", "year")
x$indicator <- sapply(1:nrow(x), function(i) sum(x$name[i]==f$name & x$year[i] >=    f$year.start & x$year[i] <= f$year.end))
x[order(x$name),]