簡體   English   中英

R 中跨列(不是行!)的滾動減法

[英]Rolling subtraction across columns (not rows!) in R

我環顧四周尋找類似的問題,但我發現的所有問題都想按 rows進行滾動減法。

我想做的是對我的 dataframe進行滾動減法 具體來說,我想按順序(從左到右)減去每一列,同時保持當前減去的累積值,作為下一個序列中要減去的“總”列。

我找到了一種對其進行硬編碼的方法,但顯然它看起來很難看,如果列數與創建的 dfs 數有任何不同,代碼就會中斷。

假設我們有一個 dataframe 每年每個年齡的人口,總數是每年的 rowSums:

df <- data.frame(Age <- c(1:40), 
                 Total <- rep(500,40), 
                 Y1990 <- rep(100,40), 
                 Y1991 <- rep(100,40),
                 Y1992 <- rep(100,40))

我想要的結果是通過以下代碼實現的:

df1 <- df$Total  #or df[2]
df2 <- df1 - df[3]
df3 <- df2 - df[4]
...
dfx <- df(x-1) - df[x+1]

#and then we join them together like so:
final_df <- cbind(df$Age, df1, df2, df3,..., dfx)

#final_df should be the Age column, the Total column (500), df2 should be 400 (500-100 = 400), df3 should be 300, etc. etc.)

我擺弄了循環,但不能完全讓第一次/最后一次迭代工作(x+1/x-1 部分一直給我一個錯誤,即下標超出范圍)。 我什至嘗試在循環中使用“break”或“next”,但我無法完全掌握它。 我有大約 70 年的數據,未來可能更多,所以我需要更新我的代碼以使其適應未來,以免有數百行“dfx”代碼。

我想知道是否有人可以為此提供一個超級簡單的循環或 function 到 go。 也許 data.table 解決方案是最簡單的,盡管我很難使用 data.table 語法。 如果您可以在整個迭代過程中保留變量名稱(盡管不是必需的),則可以加分。 我只希望我的代碼漂亮而健壯。 干杯,謝謝。

我想這就是你想要的。 不需要 40 個相同的行,5 個就足夠了:

df <- data.frame(Age = c(1:5), Total = rep(500, 5), Y1990 = rep(100, 5), Y1991 = rep(100, 5), Y1992 = rep(100, 5))

final_df <- data.frame(df[, 1:2], df$Total - t(apply(df[, 3:5], 1, cumsum)))
colnames(final_df)[-(1:2)] <- c("df2", "df3", "df4")
final_df
#   Age Total df2 df3 df4
# 1   1   500 400 300 200
# 2   2   500 400 300 200
# 3   3   500 400 300 200
# 4   4   500 400 300 200
# 5   5   500 400 300 200

這是 data.table 的解決方案:

library(data.table)
df <- data.frame(Age = c(1:5), Total = rep(500, 5), Y1990 = rep(100, 5), Y1991 = rep(100, 5), Y1992 = rep(100, 5))
setDT(df)
final_df <- cbind(df[, .(Age = Age)], 
                  df[, Reduce(`-`, .SD, init = Total, accumulate = TRUE), 
                     .SDcols = Y1990:Y1992])
final_df
  Age  V1  V2  V3  V4
1:   1 500 400 300 200
2:   2 500 400 300 200
3:   3 500 400 300 200
4:   4 500 400 300 200
5:   5 500 400 300 200

go 關於此的各種方法:

cbind(df[1], matrixStats::rowCumsums(as.matrix(df[-1])))
  Age   1   2   3   4
1   1 500 600 700 800
2   2 500 600 700 800
3   3 500 600 700 800
4   4 500 600 700 800
5   5 500 600 700 800


cbind(df[1], list2DF(Reduce('-', df[-1], accumulate = TRUE)))

  Age Var.2 Var.3 Var.4 Var.5
1   1   500   400   300   200
2   2   500   400   300   200
3   3   500   400   300   200
4   4   500   400   300   200
5   5   500   400   300   200

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM