与此页面上的问题相关:Randomly associate elements of two vectors given conditions 如果我有以下数据:
loss=c(45,10,5,1)
capitals = structure(list(capital = c(100L, 50L, 4L, 25L, 5L), loss = c(5L,
10L, 10L, 1L, 45L)), .Names = c("capital", "loss"), class = "data.frame", row.names = c(NA,
-5L))
capitals
capital loss
1 100 5
2 50 10
3 4 10
4 25 1
5 5 45
>
我正在尝试通过以下命令更正任何有损失>资本的行(从矢量损失中分配另一个随机值,以便损失< =资本):
apply(capitals, 1, function(x){while(x[2]>x[1]) {x[2] = sample(loss,1); print(x[2])} })
print函数显示函数中的值正在变化,但数据框大写中的值没有变化:
apply(capitals, 1, function(x){while(x[2]>x[1]) {x[2] = sample(loss,1); print(x[2])} })
loss
5
loss
10
loss
10
loss
1
loss
5
NULL
> capitals
capital loss
1 100 5
2 50 10
3 4 10
4 25 1
5 5 45
>
为什么资本数据框架的价值不会改变,如何纠正?谢谢你的帮助。
答案 0 :(得分:7)
apply
正在评估函数,函数内的赋值不会影响封闭环境。正在修改副本,并在函数退出时销毁该副本。
相反,要使用apply
,您应该构建一个对象,让apply
返回每个元素。也许是这样的事情:
capitals$loss <-
apply(capitals, 1,
function(x){
while(x[2]>x[1])
x[2] <- sample(loss,1)
x[2]
}
)
capitals
## capital loss
## 1 100 5
## 2 50 10
## 3 4 1
## 4 25 1
## 5 5 5
此处,loss
(x[2]
)的新值从函数返回,并由apply
收集到向量中。然后将其用于替换数据框中的列。
通过对while
的所需子集进行采样,可以在没有loss
循环的情况下完成此操作。需要if
来确定是否需要抽样:
apply(capitals, 1,
function(x)
if (x[2] > x[1])
sample(loss[loss<=x[1]], 1)
else
x[2]
)
更好的是,您可以只替换条件所在的行,而不是使用if
:
r <- capitals$capital < capitals$loss
capitals[r, 'loss'] <-
sapply(capitals[r,'capital'],
function(x) sample(loss[loss<=x], 1)
)
这里,需要替换的行由r
表示,并且只修改那些行(这与原始中while
的条件相同,但元素的顺序有被交换 - 因此从大于小于大于小于。)。
sapply
表达式为这些行循环显示capital
的值,并从loss
的那些不超过capital
值的条目返回单个样本。