Dummy为系列中的第一个新元素

时间:2012-02-03 07:50:50

标签: r time-series plyr

假设我有一个持续几个时期的变量。 就像我有一个Ipod的年数。 所以我从2001年到2004年都有Ipod第一代,然后在2005年我得到了Ipod 2等等。所以我的数据框看起来像:

  2001 Ipod1
  2002 Ipod1
  2003 Ipod1
  2004 Ipod1
  2005 Ipod2
  2006 Ipod2
  2007 Ipod2
  2008 Ipod2
  2009 Ipod3
  2010 Ipod3

我想要的是在新变量到达时创建一个假人,所以我会得到:

  Year  Var  Dummy
  2001 Ipod1  1
  2002 Ipod1  0
  2003 Ipod1  0
  2004 Ipod1  0
  2005 Ipod2  1
  2006 Ipod2  0
  2007 Ipod2  0
  2008 Ipod2  0
  2009 Ipod3  1
  2010 Ipod3  0

到目前为止,我已经能够做到这一点:

df = structure(list(Year = 2001:2010, Var = structure(c(1L, 1L, 1L,
1L, 2L, 2L, 2L, 2L, 3L, 3L), .Label = c("Ipod1", "Ipod2", "Ipod3"
), class = "factor")), .Names = c("Year", "Var"), class = "data.frame", row.names = c(NA,
-10L))

df$number.in.group = unlist(lapply(table(df$Var),seq.int)) 
df$dummy = ifelse(df$number.in.group == 1,1,0)
df$dummy[1]=0

实际上我希望假人的第一个元素为零。

我的问题是:有没有办法以更好的方式做到这一点?

由于

4 个答案:

答案 0 :(得分:9)

这个怎么样:

df$Dummy <- as.numeric(!duplicated(df$Var))

# Or, if you want the first element to be 0,
df$Dummy <- c(0, as.numeric(!duplicated(df$Var))[-1])

答案 1 :(得分:5)

我相信这会产生预期的结果:

> df$Dummy <- c(0, diff(as.numeric(df$Var)))
> df
   Year   Var Dummy
1  2001 Ipod1     0
2  2002 Ipod1     0
3  2003 Ipod1     0
4  2004 Ipod1     0
5  2005 Ipod2     1
6  2006 Ipod2     0
7  2007 Ipod2     0
8  2008 Ipod2     0
9  2009 Ipod3     1
10 2010 Ipod3     0

这是有效的,因为Var是一个因素,所以使用as.numeric工作。

答案 2 :(得分:2)

rle函数在这些情况下非常有用。它在向量中找到相同项的连续运行。

rle_result = rle(as.character(df$Var))
rle_result
Run Length Encoding
  lengths: int [1:3] 4 4 2
  values : chr [1:3] "Ipod1" "Ipod2" "Ipod3"

构建新变量:

df$new = 0
change_ids = 1 + cumsum(rle_result$lengths)
df$new[change_ids[-length(change_ids)]] <- 1
df
   Year   Var new
1  2001 Ipod1   0
2  2002 Ipod1   0
3  2003 Ipod1   0
4  2004 Ipod1   0
5  2005 Ipod2   1
6  2006 Ipod2   0
7  2007 Ipod2   0
8  2008 Ipod2   0
9  2009 Ipod3   1
10 2010 Ipod3   0

这正是你想要的地方。

答案 3 :(得分:2)

(1)问题是Dummy列,但问题中的示例答案也生成number.in.group列,因此我不确定是否需要number.in.group列;但是,下面我们假设它是必需的。请注意,将0分配给Dummy的第一个元素会将该列转换为数字:

within(df, {
    number.in.group <- ave(Year, Var, FUN = seq_along)
    Dummy <- number.in.group == 1
    Dummy[1] <- 0
})

(2a)如果不需要number.in.group并且Var中的组是连续的,那么已经提供的duplicated解决方案会更好,除非我认为它会略有如果它是这样写的更清楚:

df$Dummy <- !duplicated(df$Var)
df$Dummy[1] <- 0

即使这需要一个额外的声明。

(2b)我们也可能更喜欢非破坏性形式:

within(df, {
    Dummy <- !duplicated(Var)
    Dummy[1] <- 0
})