我想运行一个for循环,它只对数据框中某列的特定元素进行计算。元素从矩阵中的相邻列引用。我可以通过目视观察哪些元素对应于值来做到这一点 - 例如{001}元素列中的for(i in 1:5){ #
。但是,我希望能够在没有对元素编号的先验知识的情况下指定它。
e.g。在以下数据框中,我想在data.LICOR$flux
data.LICOR$day.night=='d'
的元素运行for循环
data.LICOR.day.night data.LICOR.flux
1 d 26.89
2 d 27.89
3 d 28.77
4 d 28.92
5 d 29.30
6 n 28.51
7 n 28.98
8 n 28.41
9 n 27.87
10 n 28.18
这是我之前的代码所做的,通过指定元素1:5和6:10分别对应于day.night ='d'和day.night ='n'
# replace day fluxes
for(i in 1:5){
if(data.LICOR$flux[i] > av.day.flux+2*sd.day.flux)
data.LICOR$flux[i] <- av.day.flux
else if(data.LICOR$flux[i] < av.day.flux-2*sd.day.flux)
data.LICOR$flux[i] <- av.day.flux
}
# replace night fluxes
for(i in 6:10){
if(data.LICOR$flux[i] > av.night.flux+2*sd.night.flux)
data.LICOR$flux[i] <- av.night.flux
else if(data.LICOR$flux[i] < av.night.flux-2*sd.night.flux)
data.LICOR$flux[i] <- av.night.flux
}
这将删除与均值相差大于2个标准偏差的值,并将其替换为平均值。
感谢您的任何建议。
答案 0 :(得分:8)
鉴于你对Gavin的回答的评论中的循环,我认为你想要这样的东西(假设你的例子数据在一个名为data.LICOR
的对象中)。
# within() allows us to evaluate all the expressions (the 2nd argument)
# using the data in 'data.LICOR'.
data.LICOR <- within(data.LICOR, {
# ave() applies 'FUN' to the subsets of 'flux' specified by 'day.night'
# and returns an object the same length as 'flux'.
av.flux <- ave(flux, day.night, FUN=mean);
sd.flux <- ave(flux, day.night, FUN=sd);
# ifelse() returns 'av.flux' when the first argument is TRUE
# and 'flux' when it's FALSE.
flux <- ifelse(flux > av.flux+2*sd.flux |
flux < av.flux-2*sd.flux, av.flux, flux) })
答案 1 :(得分:2)
使用subset
函数获取所需数据框的子集。例如。如果df
是您的原始数据框,则可以执行以下操作:
df.d <- subset(df, day.night == 'd')
然后你可以在df.d
上做任何你想要的计算。
要用它们的均值替换“大”和“小”值,你可以使用Joshua的方法(使用ave
和within
)或使用来自ddply
的{{1}}函数在基数R中完成plyr
包裹:
require(plyr)
## ddply breaks up the data-frame according to the value of "DayNight" ('d' or 'n') and
## WITHIN each category, "transforms" the flux column as desired
ddply(df, .(DayNight), transform,
flux = ifelse( flux > mean(flux) + 2*sd(flux) | flux < mean(flux) - 2*sd(flux),
mean(flux),
flux ))
我正在使用缩写版本的列名,但我相信你明白了。如果您知道平均值和标准偏差先验的“正确”级别,则可以使用这些值替换上述代码中的mean(flux)
和sd(flux)
。
答案 2 :(得分:2)
您可以使用以下方式获取子集:
subset(data.YSI, subset = day.night == "d")
但现在告诉我们你想用它做什么?
答案 3 :(得分:1)
Ulrich提供的最后两行答案的另一种可能性是:
flux[which(flux> av.flux+2*sd.flux & flux < av.flux-2*sd.flux)] <- av.flux
这可以说更快,因为您只需要替换那些不符合标准的值。但是,我不确定这在R中是否真的更快,对于小型数据集,我想这无关紧要。
并且循环(如果可以进行矢量化,但可能是其他语言,则不是R中的好习惯),您只需要执行此操作:
for (i in unique(data.Licor$day.night) {
if (data.LICOR$flux[which(data.LICOR$day.night==i)] > ...
请注意,这些修改是:在for语句中使用哪些因子和使用因素。