【问题标题】:Creating pointer for specific point in a dataframe为数据框中的特定点创建指针
【发布时间】:2014-02-07 05:46:53
【问题描述】:

在了解详细信息之前,先了解一下该项目的背景。我正在处理约 50 个国家/地区的列表,每个国家/地区的数据在 40 到 60 年之间。我已经能够为单个国家/地区设置一个循环,它会尝试变量的各种值(在代码中名为 DELTA)并记录结果。

我首先引入数据并将其清理为没有空值,然后使用以下代码创建一个包含用于表示每个国家/地区的所有 3 个字母代码的向量。

Clean <- na.omit(Data)
Clean <- Clean[order(country.isocode),]
Codes <- levels(Clean[,2])

然后我使用循环和子集函数为每个国家/地区创建不同的数据框。

for (i in 1:length(Codes)) {
assign((Codes[i]),droplevels(subset(Clean,country.isocode==Codes[i])))
}

现在我所有的 50 个国家都在他们自己的数据框中,以他们的 3 个字母 ISO 代码命名。以下是我运行的代码,用于为安哥拉 (AGO) 创建我想要的结果。

AGO_Results <- matrix(numeric(0), 100,2) 
AGOROW<-nrow(AGO)

for (j in 1:100) {
AGO[1,12]<-AGO[1,9]/DELTA

    for (i in 2:AGOROW) {
    AGO[i,12] <- AGO[i-1,12]*(1-DELTA)+AGO[i,9]
    }

AGO[,13] <- AGO[,12]/AGO[,8]

AGO_Results[j,1] <- DELTA
AGO_Results[j,2] <- sum(AGO[,13] > 1 & AGO[,13] < 3)

DELTA=DELTA+.002

}

在此 AGO_Results 的末尾包含我想要的值,但我不想为 50 个国家/地区手动执行此操作,因此我试图为所有 50 个国家/地区创建一个循环。我已经设法使用 eval() 和 assign() 取得了相当大的进展,但我被困在我认为的最后一个障碍上。

for (k in 1:length(Codes)) {


# Initialize Delta and Create Storage Matrix and Row Count
DELTA <- .01
assign(paste(Codes[k],"_Results", sep=""), matrix(numeric(0), 100,2))
assign(paste(Codes[k],"ROW",sep=""), nrow(eval(as.name(Codes[k]))))

这部分是完整的并且有效。现在我们遇到了真正的问题,如何引用要写入每个数据帧的单个点 [1,12]。当我每次都必须粘贴数据框的名称时,我可以做些什么来创建一个指针来替换数据框中的单个项目?

编辑:下面发布的示例数据

country country.isocode year     POP   rgdpl    ki rgdpl2wok        rgdp investment workers L.P
21  Angola             AGO 1970 5605.63 2366.51 23.27   5904.14 13265745651 3087431388 2246856 0.4 
22  Angola             AGO 1971 5752.96 2445.13 23.25   6127.95 14066747655 3270057880 2295508 0.4

【问题讨论】:

  • 你为什么要把它分成 50 个单独的数据框?这可能没有必要。您可能也不需要循环。你能发布一些示例数据吗?
  • 我添加了示例数据。由于每个国家/地区的年份长度不同,并且我要应用的函数是递归的,我认为很难让它在每个国家/地区的正确位置开始和停止。
  • 您根本不需要在正确的地方开始和停止,也不需要考虑正确的地方。使用拆分。 ?split
  • 当我最初使用 split 功能时,我无法droplevels。​​
  • 好的,但是你确定你需要droplevels吗?您可以将相关变量转换为字符(使用 as.character)。是的,您可以使用 droplevels - 不是直接在列表中,但您可以 lapply 将其添加到列表中。类似xxx &lt;- lapply(split(x, list(x$Country)), droplevels)

标签: r loops dataframe


【解决方案1】:

首先,有问题

Clean <- Clean[order(country.isocode),]

(它会使用一个全局变量country.isocode,如果有的话,数据框中没有一个。)

代替

for (i in 1:length(Codes)) {
assign((Codes[i]),droplevels(subset(Clean,country.isocode==Codes[i])))
}

你可以这样做

xyz <- split(Clean, list(country.isocode))  # or, probably Clean$country.isocode

现在您已按国家/地区拆分数据框。您可以lapply 一个函数(可能是自制的)到结果列表(xyz),然后您可以分别获得每个国家/地区的结果。试试这个,然后说你是否真的需要一个“指针”。

在 cmets 之后编辑

xyz <- split(Clean, list(Clean$country.isocode)) 
xyz <- lapply(xyz, droplevels)  # whatever that's for

现在您可以定义要对每个国家/地区执行的操作(我重写了您的代码,但并未尝试理解它的作用,但只注意到一个明显的问题):

doit <- function(x){
    # where does the DELTA come from? do you initialize it to zero?
    # anyway, you need to define it here or pass it as argument
    Results <- matrix(numeric(0), 100,2)  # I'd use 0 or NA instead of numeric(0)
    NROWs<-nrow(x)

    for (j in 1:100) {
      x[1,12]<-x[1,9]/DELTA

    for (i in 2:NROWs) {
      x[i,12] <- x[i-1,12]*(1-DELTA)+x[i,9]
    }

   x[,13] <- x[,12]/x[,8]

   Results[j,1] <- DELTA
   Results[j,2] <- sum(x[,13] > 1 & x[,13] < 3)

   DELTA=DELTA+.002
   }
   Results # returns results
   }

现在您可以将新定义的函数应用到您的列表中:

lapply(xyz, doit)

应该就是这样。您可能需要进行一些修改和反复试验,但在我看来,这是一种比使用assign 创建大量变量更明智的方法。

【讨论】:

  • 嗨,我同时接受两条建议,但写两条评论似乎有点过头了。我已经尝试过您所说的两种方法,但它似乎与我正在尝试做的事情不符。
  • 非常感谢,我对函数做了一些调整,非常棒。我很早就将 DELTA 初始化为 0.002 并附加 Clean。不熟悉编写自定义函数以及它如何与我完全不熟悉的 lapply 交互。非常感谢你和 user3207835
猜你喜欢
  • 2021-10-31
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多