简体   繁体   English

R“for loop”和/或Apply以动态转换多个变量

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

I am trying to translate/replicate into R a shorthand "for loop" technique that I would use in EViews. 我试图将我在EViews中使用的简写“for loop”技术转换/复制到R中。 I'm trying to replicate a "for loop" where I would divide one time series variable by another (vectors) and save it as a new series. 我正在尝试复制一个“for循环”,我将一个时间序列变量除以另一个(向量)并将其保存为新系列。

As I use a common naming convention (for example GDP (real), GDPn (nominal) and GDP_P (prices), see EViews example below), I can declare the list of variables once and use changes in the suffix ("n" or "_P") to create dynamic series names and loop through the calculations I need. 由于我使用通用的命名约定(例如GDP(实际),GDPn(名义)和GDP_P(价格),请参见下面的EViews示例),我可以声明一次变量列表并使用后缀中的更改(“n”或“_P”)创建动态系列名称并循环我需要的计算。 My input data is national accounts expenditure series. 我的输入数据是国民账户支出系列。

'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

So far I've tried using an R for loop (which I have read is not the preferred way in R) by creating a vector of the series name and used "assign(paste" to do the calculation. An example is below but it does not work. From what I have read about the "for" command, the declared series for "i" can only be a vector of values or a vector of names with no further context: 到目前为止,我已经尝试使用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)
}

I've also done a lot of reading into the "apply" function and derivatives, but I can't see how it works the above scenario. 我也已经对“应用”函数和衍生物进行了大量阅读,但我看不出它是如何工作的。 Any suggestions for how to do this in R is helpful. 有关如何在R中执行此操作的任何建议都很有帮助。

Your function should work like this: 你的功能应该像这样工作:

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

The get will use the strings you provide and find the vector of that name. get将使用您提供的字符串并查找该名称的向量。

There's also a non-for-loop way of doing it, using the idea from one of the answers here : 还有做它,使用从答案的一个想法的非for循环的方式在这里

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

txt will include a list of all the lines that you would have had to type to create all your vectors manually, and then eval(parse(text=txt)) takes each of those commands and executes them one by one. txt将包含您必须键入以手动创建所有向量的所有行的列表,然后eval(parse(text=txt))接受每个命令并逐个执行它们。

You can of course skip the assigning of the text to txt -- I just wanted it to be clearer what's going on here: 您当然可以跳过将文本分配给txt - 我只是希望它更清楚这里发生了什么:

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

Consider working with lists especially for many similar elements. 考虑使用列表,尤其是许多类似的元素。 Doing so you can better manage your global environment and process data more compactly and efficiently. 这样做可以更好地管理您的全球环境并更加紧凑和高效地处理数据。 For you this means maintaining 3 lists of vectors instead of 18 separate named vectors (2 original sets and new 3rd set). 对你来说,这意味着维护3个向量列表而不是18个单独的命名向量(2个原始集和新的第3集)。 The use of assign to dynamically create variables on the fly usually indicates the opportunity to use a named list. 使用assign动态创建变量通常表示有机会使用命名列表。

Specifically, gather your items in GDPn_list and GDP_list and then use Map (the non-simplified wrapper to mapply ) to iterate elementwise between both equal-length lists that calls the division function / . 具体来说,将您的项目收集在GDPn_listGDP_list中 ,然后使用Map (非简化包装器到mapply )在两个调用除法函数/等长列表之间迭代元素。 Then name the list with setNames() . 然后使用setNames()命名列表。 Below demonstrates with random data but for you as the OP can use commented out lines to build list. 下面用随机数据演示,但对于你来说,OP可以使用注释掉的行来构建列表。

Original Data 原始数据

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 ...

New Data 新数据

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 ...

And you still can reference your underlying numeric vectors via names or index numbers without losing any functionality or data: 您仍然可以通过名称或索引号引用您的基础数字向量,而不会丢失任何功能或数据:

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

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

And if equal-length vectors, build a matrix from your lists! 如果是等长矢量,请从列表中构建一个矩阵! This time using mapply : 这次使用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