R专家,
我有一个堆叠数据框,我想根据行之间的条件操作创建新列,这些列将应用于数据框中的不同组。我有一个简单的案例可以在你的最后尝试。
df<-data.frame(case=c(rep("A",6),rep("B",6)),
cond=c(rep(1:6),rep(1:6)),
param1=c(100,200,300,400,500,600,150,250,350,450,550,650),
param2=c(10,20,30,40,50,60,10,20,30,40,50,60))
这是我想要的功能 -
(1)我想基于param1和param2创建新列(例如dparam1和dparam2)。 dparam1基本上是给定&#34; cond&#34;的param1的比率。由param1 @ cond = 6标准化。基本上对于每个组,所有行都被一个特定的行划分。
带有新列的结果数据框将如下所示 -
dfnew<-data.frame(case=c(rep("A",6),rep("B",6)),
cond=c(rep(1:6),rep(1:6)),
param1=c(100,200,300,400,500,600,150,250,350,450,550,650),
param2=c(10,20,30,40,50,60,10,20,30,40,50,60),
dparam1=c(0.17,0.33,0.5,0.67,0.83,1.0,0.17,0.33,0.5,0.67,0.83,1.0),
dparam2=c(0.17,0.33,0.5,0.67,0.83,1.0,0.23,0.38,0.54,0.69,0.85,1.0))
(2)我不想指定新列的名称。新列应命名为&#34; d&#34;后跟原始列名。我想我将不得不使用粘贴功能(我不确定!)。但我有兴趣看到你的意见。
(3)最后,我想提供列名列表,我希望将规范化的新列作为此新函数的参数。
这是我目前的职能 -
param_list<-c("param1","param2")
condref<-6
fun <- function(x,list) {
for (i in list) {
if(grepl("param1|param2",i)){
x$paste(c("d",i),collapse='')<-x$i/x$i[x$cond==condref]}
else{x$paste(c("d",i),collapse='')<-x$i-x$i[x$cond==condref]}
}
x
}
dfnew<-fun(df,param_list)
And the error -
Error in x$paste(c("d", i), collapse = "") <- x$i - x$i[x$cond == condref] :
target of assignment expands to non-language object
谢谢!
答案 0 :(得分:0)
嗯,我有一个解决方案,但该死的很难看:
maxCond <- as.data.frame(t(unstack(aggregate(cond~case,df,max),cond~case)));
cbind(df,setNames(as.data.frame(do.call(rbind,lapply(unique(df$case), function(case) do.call(cbind,lapply(c('param1','param2'), function(col) round(df[df$case==case,col]/df[df$case==case&df$cond==maxCond[[case]],col],2) ))))),paste0('d',c('param1','param2'))));
## case cond param1 param2 dparam1 dparam2
## 1 A 1 100 10 0.17 0.17
## 2 A 2 200 20 0.33 0.33
## 3 A 3 300 30 0.50 0.50
## 4 A 4 400 40 0.67 0.67
## 5 A 5 500 50 0.83 0.83
## 6 A 6 600 60 1.00 1.00
## 7 B 1 150 10 0.23 0.17
## 8 B 2 250 20 0.38 0.33
## 9 B 3 350 30 0.54 0.50
## 10 B 4 450 40 0.69 0.67
## 11 B 5 550 50 0.85 0.83
## 12 B 6 650 60 1.00 1.00
您可以将其包装在函数中,如下所示:
f <- function(df,cols) { maxCond <- as.data.frame(t(unstack(aggregate(cond~case,df,max),cond~case))); cbind(df,setNames(as.data.frame(do.call(rbind,lapply(unique(df$case), function(case) do.call(cbind,lapply(cols, function(col) round(df[df$case==case,col]/df[df$case==case&df$cond==maxCond[[case]],col],2) ))))),paste0('d',cols))); };
f(df,c('param1','param2'));
## same result as above