для петли специфических элементов вектора в R - PullRequest
2 голосов
/ 28 февраля 2011

Я хочу запустить цикл for, который выполняет вычисления только для определенных элементов из столбца во фрейме данных.На элементы ссылаются из соседнего столбца в матрице.Я могу сделать это, визуально наблюдая, какие элементы соответствуют значениям - например, for(i in 1:5){ # в столбце из 301 элемента.Однако я хотел бы иметь возможность указать это без априорного знания номеров элементов.

например, в следующем кадре данных я хочу запустить цикл for для элементов столбца data.LICOR$flux при data.LICOR$day.night=='d'

   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 ]

8 голосов
/ 28 февраля 2011

Учитывая циклы в вашем комментарии к ответу Гэвина, я думаю, вы хотите что-то вроде этого (при условии, что ваши примеры данных находятся в объекте с именем 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) })
2 голосов
/ 28 февраля 2011

Вы можете получить подмножество, используя:

subset(data.YSI, subset = day.night == "d")

Но теперь скажите нам, что вы хотите с ним сделать?

2 голосов
/ 28 февраля 2011

Используйте функцию subset, чтобы получить подмножество необходимого вам фрейма данных. Например. если df ваш исходный фрейм данных, вы можете сделать:

df.d <- subset(df, day.night == 'd')

И тогда вы можете делать все, что захотите, на df.d. Чтобы заменить «большие» и «маленькие» значения их средними, вы можете сделать это в базе R, используя подход Джошуа (используя ave и within) или используя функцию ddply из пакета 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 ))

Я использую сокращенные версии имен ваших столбцов, но я уверен, что вы поняли идею. Если вам известен «правильный» уровень среднего и стандартного отклонения a priori , вы можете заменить mean(flux) и sd(flux) в приведенном выше коде этими значениями.

1 голос
/ 01 марта 2011

Другая возможность для последних двух строк ответа, представленного Ульрихом:

 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)] > ...

Обратите внимание, что здесь есть изменения: использование which и использование факторов в операторе for.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...