简体   繁体   English

R版SAS宏变量?

[英]R Version of SAS macro variable?

I am pretty familiar with SAS. 我对SAS很熟悉。 I am a beginner in R and am trying to figure out what the R equivalent of macro variables is. 我是R的初学者,我试图找出R等价的宏变量是什么。 Specifically I have 6 datasets with a common variable name, Price. 具体来说,我有6个数据集,其公共变量名称为Price。 I want to create a loop that changes Price in each data set to DatasetNamePrice. 我想创建一个循环,将每个数据集中的Price更改为DatasetNamePrice。 This would be simple in SAS using macro variables for text replacement. 在使用宏变量进行文本替换的SAS中,这很简单。 So far I have created vector with the names of each data set. 到目前为止,我已经创建了带有每个数据集名称的向量。

v=c("SP","SPF","SPP","NQ","RTY","NYA")

I usually use this code to rename variables: 我通常使用此代码重命名变量:

names(SP)[names(SP)=="Price"]="SPPrice"

My attempt so far is: 我到目前为止的尝试是:

for(i in 1:6) 
{ 
  names(v[[i]])[names(v[[i]])=="Price"]="v[[i]]Price"
}

R does not give me any errors when this runs but does not appear to do anything. R在运行时没有给我任何错误,但似乎没有做任何事情。 Any help is appreciated. 任何帮助表示赞赏。

Here are some alternatives. 这是一些替代方案。

1) Base R Set e to be the environment of the data frames. 1)Base Re设置为数据帧的环境。 Here we assume they are in the current environment. 在这里,我们假设它们处于当前环境中。 With this in place e[[nm]] refers to the data frame whose name is the character string held in variable nm so the following works modifying the names in place: 有了这个, e[[nm]]指的是数据框,其名称是变量nm保存的字符串,因此以下工作可以修改名称:

e <- environment()
for(nm in v) {
   is.price <- names(e[[nm]]) == "Price"
   names(e[[nm]])[ is.price ] <- paste0(nm, "Price")
}

1a) Base R Function passing name and environment Here we define a function which takes the name of the data frame and the environment and modifies the names of the data frame in place. 1a)Base R函数传递名称和环境这里我们定义一个函数,它接受数据框和环境的名称,并修改数据框的名称。 We use match instead of == so that from and to can optionally be vectors of names. 我们使用match而不是==因此fromto可以选择是名称的​​向量。 The in place modification in this solution is not really in the spirit of R's functional nature but we show it as an alternative: 此解决方案中的原位修改并非真正符合R的功能性,但我们将其作为替代方案展示:

rename1a <- function(DFname, from, to, envir = parent.frame()) {
    ix <- match(from, names(envir[[DFname]]))
    names(envir[[DFname]])[ ix ] <- to
}

for(nm in v) rename1a(nm, "Price", paste0(nm, "Price"))

1b) Base R Function returning copy Here we define a function which takes the data frame itself and returns a copy with the name changed. 1b)Base R函数返回副本这里我们定义一个函数,它接受数据帧本身并返回名称已更改的副本。 The function itself does not need to deal with environments and is more funtional in nature (ie it does not modify its inputs) -- the caller is responsible for assigning the result back. 函数本身不需要处理环境,本质上更具功能性(即它不会修改其输入) - 调用者负责将结果分配回来。

rename1b <- function(DF, from, to) {
    names(DF)[match(from, names(DF))] <- to
    DF
}

e <- environment()
for(nm in v) e[[nm]] <- rename1b(e[[nm]], "Price", paste0(nm, "Price"))

2) doBy::renameCol renameCol in the doBy package is plug compatible with rename1b in (1b) so: 2)doBy :: renameCol renameCol在doBy包是与插头兼容rename1b (1b)中,以便:

library(doBy)
e <- environment()
for(nm in v) e[[nm]] <- renameCol(e[[nm]], "Price", paste0(nm, "Price"))

3) plyr::rename The plyr package has a rename function. 3)plyr :: rename plyr包具有rename功能。 Note that like (1b) it produces a copy of the data frame with the renamed columns so we assign it back: 请注意,与(1b)类似,它会使用重命名的列生成数据框的副本,因此我们将其分配回来:

e <- environment()
for(nm in v) e[[nm]] <- plyr::rename(e[[nm]], list(Price = paste0(nm, "Price")))

The reshape package has a similar function also called rename and the above works if we replace plyr::rename with reshape::rename . reshape包有一个类似的函数,也称为rename ,如果我们用reshape::rename替换plyr::rename ,上面的工作就可以了。

4) gtools::defmacro It would also be possible to use defmacro in gtools to create a macro which alters the names in place. 4)gtools :: defmacro这也将有可能使用defmacro在gtools创建它改变了地点名称的宏。 Although not typical of processing in R this does allow one to pass the data frame itself rather than separate name and environment as in (1a). 虽然不是典型的R中的处理,但这确实允许人们传递数据帧本身,而不是如(1a)中那样单独的名称和环境。

library(gtools)
rename4 <- defmacro(DF, from, to, expr = { names(DF)[ match(from, names(DF)) ] <- to })

e <- environment()
for(nm in v) rename4(e[[nm]], "Price", paste0(nm, "Price"))

Also see Thomas Lumley's Programmer's Niche article in R News 2001/3 . 另见Thomas Lumley在R News 2001/3中的程序员的Niche文章。

Note 1: You may wish to examine why you want to make these name changes in first place. 注1:您可能希望首先检查您想要更改这些名称的原因。 There is also the question of whether the data frames should be freely defined in the global environment or combined into a list given that we want to deal with them en masse. 还有一个问题是数据框架是应该在全球环境中自由定义还是组合成一个列表,因为我们希望大体上处理它们。 The first Map creates a named list L such that, for example, L$SP or L[["SP"]] refers to the SP component in L . 第一个Map创建一个命名列表L ,例如, L$SPL[["SP"]]指的是LSP组件。 The second Map outputs a new named list whose components have the new column names: 第二个Map输出一个新的命名列表,其组件具有新的列名:

L <- Map(get, v) # create named list of input data frames
Map(rename1b, L, "Price", paste0(names(L), "Price"))

Note 2: Here we create some input to test with using the builtin data frame BOD . 注2:这里我们使用内置数据框BOD创建一些输入进行测试。 This creates the objects SP , SPF , etc. that are the same as data frame BOD except that the second column is named "Price" : 这将创建与数据框BOD相同的对象SPSPF等,但第二列名为"Price"

# create SP, SPF, ... to test, each with a Price column
v <- c("SP","SPF","SPP","NQ","RTY","NYA")
for(nm in v) assign(nm, setNames(BOD, c("Time", "Price")))

For your needs, you will need the get() and assign() functions since you are attempting to pass a string literal in the names() attribute which expects a data frame object. 根据您的需要,您将需要get()assign()函数,因为您尝试在要求数据框对象的names()属性中传递字符串文字。 Also, to concatenate variables with strings you need to use paste() . 另外,要使用字符串连接变量,您需要使用paste()

Consider the following that uses lapply() (a recursive method to apply a function to list or vector and returns a list); 考虑以下使用lapply() (将函数应用于列表或向量并返回列表的递归方法); it renames the fields and returns each data frame into a list of data frames. 它重命名字段并将每个数据帧返回到数据帧列表中。 Then, a for loop re-writes the original data frames from this created list using assign() : 然后, for循环使用assign()从此创建的列表中重写原始数据帧:

v=c("SP","SPF","SPP","NQ","RTY","NYA")

dfList <- lapply(v, function(x) {
                      df <- get(x)
                      names(df)[grep("Price", names(df))] <- paste0(x, "Price")              
                      return(df)    
                })

for (i in 1:length(v)) {  
     assign(v[[i]], as.data.frame(dfList[[i]]))  
}

rm(dfList)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM