【问题标题】:R loop through columns of a data frame to create new cols based on start end yearsR循环遍历数据框的列以根据开始结束年份创建新的列
【发布时间】:2014-09-06 04:19:10
【问题描述】:

我有一个这样的开始/结束年份的租约数据框

region=c("a","b","c","d")
lease=c("x","y","z","k")
startyr=c(2000,2001,2003,2002)
endyr=c(2004,2004,2006,2005)
annualAmt=c(7000,8500,6000,5500)
df=data.frame(region,lease,startyr,endyr,annualAmt)

我想通过将数据框重塑为所需的输出来分散年份:

region lease 2000 2001 2002 ... 2006
a x 7000 7000 7000 7000 7000 0 0
b y 0 8500 8500 8500 8500 0 0 

逻辑是,如果租约涵盖 2000-2004 年,则其金额将计入 2000,2001..2004 列

最好的方法是什么? 如果我写一个循环,我应该如何命名新创建的年份 cols 2000-2006? 还是应该使用 apply?

【问题讨论】:

  • 你也可以发布你想要的输出吗?
  • 已添加。谢谢。 @AnandaMahto

标签: r loops datetime reshape


【解决方案1】:

这是一个主要涉及基本加法和减法的替代方案:

Rows <- df$endyr - df$startyr               # How many times to repeat rows?
df <- df[rep(rownames(df), Rows), ]         # Repeat the rows
df$year <- df$startyr + sequence(Rows) - 1  # Add a new "year" variable
reshape(df, direction = "wide",             # Reshape, long to wide
        idvar = c("region", "lease"),       # idvars are the first two cols
        timevar = "year",                   # timevar is the new year col
        drop = c("startyr", "endyr"))       # and drop the start/endyr cols
#   region lease annualAmt.2000 annualAmt.2001 annualAmt.2002
# 1      a     x           7000           7000           7000
# 2      b     y             NA           8500           8500
# 3      c     z             NA             NA             NA
# 4      d     k             NA             NA           5500
#   annualAmt.2003 annualAmt.2004 annualAmt.2005
# 1           7000             NA             NA
# 2           8500             NA             NA
# 3           6000           6000           6000
# 4           5500           5500             NA

或者,您可以使用“data.table”,如下所示:

library(data.table)
## Start with your original df
dt <- data.table(df)
dcast.data.table(
  DT[, list(year = seq(startyr, endyr), 
            annualAmt), 
     by = list(region, lease)], 
  region + lease ~ year, 
  value.var = "annualAmt", fill = 0)
#    region lease 2000 2001 2002 2003 2004 2005 2006
# 1:      a     x 7000 7000 7000 7000 7000    0    0
# 2:      b     y    0 8500 8500 8500 8500    0    0
# 3:      c     z    0    0    0 6000 6000 6000 6000
# 4:      d     k    0    0 5500 5500 5500 5500    0

【讨论】:

    【解决方案2】:

    怎么样

    years <- seq(min(df$startyr), max(df$endyr))
    
    dd <- data.frame(region, lease, t(mapply(function(a,b, v) {
        v* !is.na(match(years, seq(a, b)))
    }, startyr, endyr, annualAmt)))
    
    names(dd)[-(1:2)]<-years
    dd
    

    返回

      region lease 2000 2001 2002 2003 2004 2005 2006
    1      a     x 7000 7000 7000 7000 7000    0    0
    2      b     y    0 8500 8500 8500 8500    0    0
    3      c     z    0    0    0 6000 6000 6000 6000
    4      d     k    0    0 5500 5500 5500 5500    0
    

    【讨论】:

    • 非常整洁。但是,我不明白为什么 mapply 输出被转置
    猜你喜欢
    • 1970-01-01
    • 2021-03-31
    • 1970-01-01
    • 2019-08-26
    • 2018-09-28
    • 2023-02-04
    • 2021-02-08
    • 2013-03-04
    • 1970-01-01
    相关资源
    最近更新 更多