2016-11-23 50 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] 
相關問題