2016-11-23 45 views
-1

我想为实际栏目做一个rowSum。不过,我希望将某些观察值的数值包含在UpTo之前。这是该数据帧:R中的衣衫褴褛的rowsums

dat <- structure(list(Company = c("ABC", "DEF", "XYZ"), UpTo = c(NA, 
"Q2", "Q3"), Actual.Q1 = c(100L, 80L, 100L), Actual.Q2 = c(50L, 
75L, 50L), Forecast.Q3 = c(80L, 50L, 80L), Forecast.Q4 = c(90L, 
80L, 100L)), .Names = c("Company", "UpTo", "Actual.Q1", "Actual.Q2", 
"Forecast.Q3", "Forecast.Q4"), class = "data.frame", row.names = c("1", 
"2", "3")) 

    Company UpTo Actual.Q1 Actual.Q2 Forecast.Q3 Forecast.Q4 
1  ABC NA  100  50   80   90 
2  DEF Q2  80  75   50   80 
3  XYZ Q3  100  50   80   100 
  • 对于公司ABC,因为没有UpTo日期,它将是Actual.Q1 + Actual.Q2,这是150
  • 对于公司DEF,因为UpTo日期Q2,这将是Actual.Q1 + Actual.Q2,这是155
  • 对于公司XYZ,因为UpTo日期是Q3,它将Actual.Q1 + Actual.Q2 + Forecast.Q3,这是230

所得数据帧应该是这样的:

Company UpTo Actual.Q1 Actual.Q2 Forecast.Q3 Forecast.Q4 SumRecent 
1  ABC NA  100  50   80   90  150 
2  DEF Q2  80  75   50   80  155 
3  XYZ Q3  100  50   80   100  230 

我曾尝试使用rowSums功能。但是,它不会生效变量UpTo。任何帮助表示赞赏。谢谢!

+0

如果它是NA,它只会是Q1 + Q2,因为如果没有指定最新日期,我们只想要实际值。 –

回答

1

这是一个可能性:

df$SumRecent <- sapply(1:nrow(df), function(x) {sum(df[x,3:ifelse(is.na(grep(df[x,2], colnames(df))[1]), 4, grep(df[x,2], colnames(df))[1])])}) 


# Company UpTo Actual.Q1 Actual.Q2 Forecast.Q3 Forecast.Q4 SumRecent 
# 1  ABC <NA>  100  50   80   90  150 
# 2  DEF Q2  80  75   50   80  155 
# 3  XYZ Q3  100  50   80   100  230 

我们期待与在dfcolnames(df))列名列UpTodf[x,2])使用grep的匹配值。如果我们发现我们得到的总和,如果我们不觉得我们只是总结的值列3和4

+0

根据经验,我真的很讨厌自己在data.frame中使用数字引用。改用名称,永远相信我!在这种情况下,当事情因列位发生变化而中断时,简洁是不值得的。 –

+0

@BrandonBertelsen:我同意它可以给出一些问题,但在这种情况下,如果不使用数字引用,我们将不得不查看每个以QXXX结尾的列名,确保它们的顺序不断增加,等等,这似乎使问题复杂化太多。(或者你有更快的解决方案吗?)我假定数据的格式被固定来回答这个问题。 – etienne

+0

这不是一种批评,一般而言,在R这样的编程方面只是一个谨慎的词语。 Stackoverflow的答案有很大的影响力。所以谨慎小心对于新程序员是有用的:) –

1

我们可以使用二进制加权的行数和。

UpTo <- as.character(dat$UpTo) ## in case you have factor column 
UpTo[is.na(UpTo)] <- "Q2" ## replace `NA` to "Q2" 
w <- outer(as.integer(substr(UpTo, 2, 2)), 1:4, ">=") 
#  [,1] [,2] [,3] [,4] 
#[1,] TRUE TRUE FALSE FALSE 
#[2,] TRUE TRUE FALSE FALSE 
#[3,] TRUE TRUE TRUE FALSE 

我们有一个逻辑矩阵。不过,这并不影响算术计算为TRUE是1和FALSE是0,然后我们做加权行总和:

X <- data.matrix(dat[3:6]) 
dat$SumRecent <- rowSums(X * w) 

# Company UpTo Actual.Q1 Actual.Q2 Forecast.Q3 Forecast.Q4 SumRecent 
#1  ABC <NA>  100  50   80   90  150 
#2  DEF Q2  80  75   50   80  155 
#3  XYZ Q3  100  50   80   100  230 

这种方法的优点是它的速度/效率,因为它是完全量化。这种方法是超快速。您可以参考Fast way to create a binary matrix with known number of 1 each row in R中的基准测试结果。

0

这也应该工作:使用数据表

df$UpTo <- as.character(df$UpTo) 
df$SumRecent <- apply(df, 1, function(x) ifelse(is.na(x[2]), sum(as.integer(x[3:4])), 
              sum(as.integer(x[3:(grep(x[2], names(df)))])))) 
df 

#  Company UpTo Actual.Q1 Actual.Q2 Forecast.Q3 Forecast.Q4 SumRecent 
#1  ABC <NA>  100  50   80   90  150 
#2  DEF Q2  80  75   50   80  155 
#3  XYZ Q3  100  50   80   100  230 
0

另一种方法:

require(data.table) 
dat <- fread('Company UpTo Actual.Q1 Actual.Q2 Forecast.Q3 Forecast.Q4 
      ABC NA  100  50   80   90 
      DEF Q2  80  75   50   80 
      XYZ Q3  100  50   80   100') 

dat[, SumRecent:= ifelse(is.na(UpTo), Actual.Q1 + Actual.Q2, 
             sum(.SD[, grepl(paste0("Q[1-", substring(UpTo, 2), "]$"), names(.SD)), with = F])), by = Company] 
相关问题