【问题标题】:Applying functions to dataframe or multiple lists将函数应用于数据框或多个列表
【发布时间】:2013-03-16 17:53:49
【问题描述】:

根据 cmets 编辑: OP想要计算:

(100 *  (1 - 10 ^ - (Do - Do[Do==0] )) ⎞ (1 - 10 ^ - (Do[Do==100] - Do[Do==0]) - Do

对于data.frameClInSa 的每个组合
-RS


我正在尝试将一个名为 dG 的函数应用于数据帧。由于函数的参数长度不同,回收产生了不可预知的结果。

为了纠正这个问题,我将数据框分成列表,并尝试在使用名为“ids”的函数识别每个列表后将 dG 函数(如下)应用于每个列表。

  • 请随时提出不同的解决方案。仅供参考,我的具体要求从要点开始

请让我先提供显示问题的综合数据:

Do <- rep(c(0,2,4,6,8,10,15,20,30,40,45,50,55,60,65,70,80,85,90,92,94,96,98,100), each=16,times=16)
Cl <- rep(c("K", "Y","M","C"), each= 384, times=4)
In <- rep(c("A", "S"), each=3072)
Sa <- rep(c(1,2), each=1536)
Data <- rnorm(6144)
DataFrame <- cbind.data.frame(Do,Cl,In,Sa,Data); head(DataFrame)
rm(Do,Cl,In,Sa,Data)
attach(DataFrame)

DFSplit <- split(DataFrame[ , "Data"], list(Do, Cl, In, Sa))

函数 'ids' 是一个辅助函数,用于识别列表名称

ids <- function(Do, Cl, In, Sa){
    grep( paste( "^" , Do, "\\.",
                Cl, "\\.",
                In,
                "\\.", Sa,sep=""),
         names(DFSplit), value = TRUE)}

mapply(ids, Do, Cl, In, Sa, SIMPLIFY = FALSE)

上面的 mapply 产生了 6144 个列表。如果您查看 mapply 输出,您会注意到有 384 个唯一列表名称,但每个名称重复 16 次 384*16=6144。

  • 如何更改 'ids' 函数,使 mapply 不会重复 16 次相同的名称。

作为一个丑陋且昂贵的解决方案,我使用了独特的;我需要一个更好的基本解决方案。

unique(mapply(ids, Do, Cl, In, Sa, SIMPLIFY = FALSE))

dG 函数是我想要对每个“DFSplit”列表进行操作的函数。它与之前的 ids 函数有相同的问题。它使用 ids 函数作为输入。

dG <- function(Do,Cl, In, Sa){
    dg <- 100*
                (1-10^-( DFSplit[[ids(Do,  Cl, In, Sa)]] - DFSplit[[ids(0, Cl, In, Sa)]])) /
                (1-10^-( DFSplit[[ids(100, Cl, In, Sa)]] - DFSplit[[ids(0, Cl, In, Sa)]])) - Do
    dg}

我尝试如下使用 dG,但这不是我想要的。

dG(Do,Cl, In, Sa)

它只评估了 dG 函数的最后一部分 (-Do) 加上这个警告

在 grep(paste("^", unique(Do), "\.", unique(Cl), "\.", unique(In), : 参数 'pattern' 的长度 > 1 并且只有第一个将使用元素

  • 能否建议对 dG 函数进行修改

然后我尝试了mapply

mapply(dG, Do, Cl, In, Sa, SIMPLIFY = FALSE)

mapply 使用我的数据正确评估了函数。 mapply 生成 6144 个列表。您会注意到,mapply 输出基本上是 384 个唯一列表,每个列表重复 16 次 384*16=6144。

  • 如何修改 dG 函数以摆脱无用且耗时的重复?

我的想法是:

  1. 消除我的第一个函数“ids”中的重复,我不知道该怎么做 .
  2. 更改第二个函数的参数,使参数的长度为 384。也许使用列表的名称作为输入参数。我不知道该怎么做。

  3. 更改公式 dG,不要使用 (Do, Cl, In, Sa) 参数,因为每个参数的长度为 6144

【问题讨论】:

  • 您的代码返回Error: object 'DFSplit' not found。您如何将其大幅简化为长度不是 384 个独特元素,而更像是 3 个元素,以便人们可以看到您实际尝试做的事情。
  • @Chase,DFSplit 在这里。 stackoverflow.com/questions/15449612/… OP 可能仍然在环境中,因此忽略了错误
  • 对不起,蔡斯,我从复制/粘贴中得到的。现在是正确的
  • 我同意里卡多的建议。我认为您可能使这完全太复杂了。我非常怀疑是否需要先拆分成单独的列表,有 几个 R 函数可以按操作进行分组。可以在here 找到其中的一个子集以及计时结果。更重要的是,我建议您查看 this 并进行相应的编辑。
  • 这是一个很好的例子,简单地向人们提供必要的信息,让他们更容易提供帮助。如果您可以简单地说明您要计算的内容,人们会为您提供大量有用的建议来说明如何进行计算。请不要让人猜你在做什么。

标签: r


【解决方案1】:

更新:

您对@Roland 所做的评论是您必须在每个previous related questions 中添加的所有内容,这曾经包括在内。

您的整个流程可以在一行代码中处理:

library(data.table)
myDT <- data.table(DataFrame)

myDT[ , "TVI" :=  100 * (1 - 10^-(Data - Data[Do==0])) / (1 - 10^-(Data[Do==100] - Data[Do==0])) 
      , by=list(Cl, In, Sa)]

# this is your Tonval Value Increase
myDT$TVI


原答案:

仍然非常不清楚您要完成什么。但是,这里有两个概念应该能够为您节省一个令人头疼的世界。

首先,您不需要ids 函数。您可以通过expand.grid获得更多里程:

myIDs <- expand.grid(unique(Do), unique(Cl), unique(In), unique(Sa))

# You can then use something like 
apply(myIDs, 1, paste, sep=".")
# to get the same results.  Or whatever other function suits

但是,即使这样也不是必须的。


这是使用 data.tabledG 函数的等效项。

请注意,不需要任何拆分或ids 或类似的东西。
一切都由data.table 中的by 函数处理。

library(data.table)
myDT <- data.table(DataFrame)

myDT

dG_DT <- 
    100 * 
    1 - 10^(   myDT[ ,     Data, by=list(Do, Cl, In, Sa)][, Data] 
             - myDT[Do==0, Data, by=list(Do, Cl, In, Sa)][, Data]
            ) / 

    1 - 10^(   myDT[Do==100, Data, by=list(Do, Cl, In, Sa)][, Data]
             - myDT[Do==0,   Data, by=list(Do, Cl, In, Sa)][, Data]
            ) - 
    myDT[, Do]

dG_DT

【讨论】:

  • Ricardo Saporta,非常感谢您完全回答了我的问题。你能解释一下你的解决方案细节吗?但是,您提供的公式是总点面积。要获得 TVI,我们必须按如下方式减去点值: myDT[ , "TVI" := (100 * (1 - 10^-(Data - Data[Do==0])) / (1 - 10^-(数据[Do==100] - 数据[Do==0]))- Do) , by=list(Cl, In, Sa)]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 2021-03-20
  • 2019-06-15
  • 1970-01-01
  • 2021-08-09
  • 2015-12-26
  • 1970-01-01
相关资源
最近更新 更多