用于R中向量的循环特定元素

时间:2011-02-28 18:36:40

标签: r

我想运行一个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个标准偏差的值,并将其替换为平均值。

感谢您的任何建议。

4 个答案:

答案 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的方法(使用avewithin)或使用来自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语句中使用哪些因子和使用因素。