簡體   English   中英

R“for loop”和/或Apply以動態轉換多個變量

[英]R “for loop” and/or Apply to transform several variables dynamically

我試圖將我在EViews中使用的簡寫“for loop”技術轉換/復制到R中。 我正在嘗試復制一個“for循環”,我將一個時間序列變量除以另一個(向量)並將其保存為新系列。

由於我使用通用的命名約定(例如GDP(實際),GDPn(名義)和GDP_P(價格),請參見下面的EViews示例),我可以聲明一次變量列表並使用后綴中的更改(“n”或“_P”)創建動態系列名稱並循環我需要的計算。 我的輸入數據是國民賬戶支出系列。

'EViews shorthand "for next" loop:

%CATS = "GDP CONS INV GOV EX IM"
 for %CATS {%cats}
   series {%cats}_P= {%cats}n / {%cats}
 next

'Which is shorthand replication of below ("series" declares a series of the subsequent name):

series GDP_P    = GDPn / GDP
series CONS_P   = CONSn / CONS
series INV_P    = INVn /  INV
series GOV_P    = GOVn / GOV
series EX_P     = EXn / EX
series IM_P     = IMn / IM

到目前為止,我已經嘗試使用R for循環(我已經讀過它不是R中的首選方法),通過創建系列名稱的向量並使用“assign(paste”來進行計算。示例如下,但它從我所讀到的“for”命令來看,“i”的聲明系列只能是值的向量或沒有進一步上下文的名稱向量:

cats<-c("GDP","CONS","GOV","INV","EX","IM")
for (i in cats){
  assign(paste(i, "_P",sep=""), paste(i, "n",sep="")/i)
}

我也已經對“應用”函數和衍生物進行了大量閱讀,但我看不出它是如何工作的。 有關如何在R中執行此操作的任何建議都很有幫助。

你的功能應該像這樣工作:

cats<-c("GDP","CONS","GOV","INV","EX","IM")
for (i in cats){
  assign(paste(i, "_P",sep=""), get(paste(i, "n",sep=""))/get(i))
}

get將使用您提供的字符串並查找該名稱的向量。

還有做它,使用從答案的一個想法的非for循環的方式在這里

txt<-paste0(cats, "_P <- ", cats, "n/", cats)
eval(parse(text=txt))

txt將包含您必須鍵入以手動創建所有向量的所有行的列表,然后eval(parse(text=txt))接受每個命令並逐個執行它們。

您當然可以跳過將文本分配給txt - 我只是希望它更清楚這里發生了什么:

eval(parse(text=paste0(cats, "_P <- ", cats, "n/", cats)))

考慮使用列表,尤其是許多類似的元素。 這樣做可以更好地管理您的全球環境並更加緊湊和高效地處理數據。 對你來說,這意味着維護3個向量列表而不是18個單獨的命名向量(2個原始集和新的第3集)。 使用assign動態創建變量通常表示有機會使用命名列表。

具體來說,將您的項目收集在GDPn_listGDP_list中 ,然后使用Map (非簡化包裝器到mapply )在兩個調用除法函數/等長列表之間迭代元素。 然后使用setNames()命名列表。 下面用隨機數據演示,但對於你來說,OP可以使用注釋掉的行來構建列表。

原始數據

cats <- c("GDP","CONS","GOV","INV","EX","IM")

set.seed(9272018)
GDPn_list <- setNames(replicate(6, runif(50)*120, simplify=FALSE), paste0(cats, "n"))
# GDPn_list <- list(GDPn, CONSn, GOVn, INVn, EXn, IMn)

str(GDPn_list)
# List of 6
#  $ GDPn : num [1:50] 52.4 31.9 10.6 118.4 66 ...
#  $ CONSn: num [1:50] 18.27 22.3 95.13 87.44 9.79 ...
#  $ GOVn : num [1:50] 48.83 69.73 113.61 35.53 1.21 ...
#  $ INVn : num [1:50] 51.9 96.9 28.2 67.2 19 ...
#  $ EXn  : num [1:50] 28.3 94.3 42.3 65.5 83.6 ...
#  $ IMn  : num [1:50] 109.3 26.6 60.2 78.2 55.5 ...

GDP_list <- setNames(replicate(6, runif(50)*100, simplify=FALSE), cats)
# GDPn_list <- list(GDP, CONS, GOV, INV, EX, IM)

str(GDP_list)    
# List of 6
#  $ GDP : num [1:50] 51.1 65.9 41.5 24.5 87.3 ...
#  $ CONS: num [1:50] 47.66 77.32 46.97 48.61 2.98 ...
#  $ GOV : num [1:50] 32.6 70.3 21.5 73.4 97.8 ...
#  $ INV : num [1:50] 80.7 16.8 57.4 80.7 12.1 ...
#  $ EX  : num [1:50] 38.1 78.1 40.6 62.8 61.9 ...
#  $ IM  : num [1:50] 39.8 84.8 11.4 39.7 14.7 ...

新數據

GDPp_list <- setNames(Map(`/`, GDPn_list, GDP_list), paste0(cats, "p"))

str(GDPp_list)    
# List of 6
#  $ GDPp : num [1:50] 1.025 0.484 0.256 4.835 0.756 ...
#  $ CONSp: num [1:50] 0.383 0.288 2.025 1.799 3.286 ...
#  $ GOVp : num [1:50] 1.4969 0.9921 5.2891 0.4844 0.0124 ...
#  $ INVp : num [1:50] 0.644 5.775 0.491 0.832 1.578 ...
#  $ EXp  : num [1:50] 0.744 1.207 1.043 1.043 1.352 ...
#  $ IMp  : num [1:50] 2.747 0.314 5.293 1.971 3.783 ...

您仍然可以通過名稱或索引號引用您的基礎數字向量,而不會丟失任何功能或數據:

GDPp_list$GDPp
GDPp_list$CONSp
GDPp_list$GOVp
...

GDPp_list[[1]]
GDPp_list[[2]]
GDPp_list[[3]]
...

如果是等長矢量,請從列表中構建一個矩陣! 這次使用mapply

GDPp_matrix <- mapply(`/`, GDPn_list, GDP_list)
colnames(GDPp_matrix) <- paste0(cats, "p")

head(GDPp_matrix)

#           GDPp      CONSp       GOVp       INVp       EXp      IMp
# [1,] 1.0252871  0.3832836 1.49687150  0.6436575 0.7441159 2.746551
# [2,] 0.4835700  0.2884577 0.99208666  5.7753575 1.2067694 0.314102
# [3,] 0.2562130  2.0251752 5.28913247  0.4910816 1.0429316 5.292843
# [4,] 4.8345697  1.7987625 0.48436284  0.8322211 1.0431301 1.970523
# [5,] 0.7563794  3.2859395 0.01236608  1.5781949 1.3518592 3.783420
# [6,] 0.1515318 10.9332338 1.10608066 13.7953500 0.7211371 1.918249

暫無
暫無

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

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