Кумулятивная сумма и организация данных

У меня есть около 40000 значений данных об осадках из разных выборок, которые будут постоянно обновляться. Файл csv организован следующим образом:

NAME;       YEAR;   ID;     VALUE
Sample1;    1998;   354;    45
Sample1;    1999;   354;    23
Sample1;    2000;   354;    66
Sample1;    2001;   354;    98
Sample1;    2002;   354;    36
Sample1;    2003;   354;    59
Sample1;    2004;   354;    64
Sample1;    2005;   354;    23
Sample1;    2006;   354;    69
Sample1;    2007;   354;    94
Sample1;    2008;   354;    24
Sample2;    1964;   1342;    7
Sample2;    1965;   1342;   24
Sample3;    2002;   859;    90
Sample3;    2003;   859;    93
Sample3;    2004;   859;    53
Sample3;    2005;   859;    98 

Что я хотел бы сделать со сценарием R, так это следующее: Создайте новую строку, где для группы образцов (например, для всех Sample1, а затем начните заново со значения для всех Sample2, а затем начните заново со значения для всех Sample3 и так далее) суммируются на основе предыдущего значения (совокупная сумма данных об осадках), например, для образца 1 результаты в строке, как в этом примере, CUM_RAINFALL (для первого примера что-то вроде этого: 45 для CUM_RAINFALL 1, а затем 45+ 23, а затем 68 + 66, а затем 134 + 232 и так далее до конца Sample1, значение Sample2 должно быть принято, и процедура должна начаться заново)

NAME;       YEAR;   ID;     VALUE    CUM_RAINFALL
Sample1;    1998;   354;    45;       45
Sample1;    1999;   354;    23;       68
Sample1;    2000;   354;    66;      134
Sample1;    2001;   354;    98;      232
Sample1;    2002;   354;    36;      268
Sample1;    2003;   354;    59;      327
Sample1;    2004;   354;    64;      391
Sample1;    2005;   354;    23;      414
Sample1;    2006;   354;    69;      483
Sample1;    2007;   354;    94;      577
Sample1;    2008;   354;    24;      601
Sample2;    1964;   1342;    7;      7
Sample2;    1965;   1342;   24;      31
Sample3;    2002;   859;    90;      90
Sample3;    2003;   859;    93;      183
Sample3;    2004;   859;    53;      236
Sample3;    2005;   859;    98;      334

Исходя из этого, я хотел бы написать новый файл, содержащий все строки, которые имеют более 3 значений (в данном примере Sample2 не будет записан в файл, потому что он содержит только 2 значения)

Есть ли простой способ сделать это в R? Любая помощь приветствуется! По следующей ссылке вы найдете CSV с данными: https://dl.dropboxusercontent.com/u/16277659/sample.cs


person kurdtc    schedule 02.08.2014    source источник


Ответы (3)


40k наблюдений должны работать в базе R.

d$CUMRAIN <- unlist(by(d$VALUE, d$NAME, cumsum), use.names = FALSE)
d
#       NAME YEAR   ID VALUE CUMRAIN
# 1  Sample1 1998  354    45      45
# 2  Sample1 1999  354    23      68
# 3  Sample1 2000  354    66     134
# 4  Sample1 2001  354    98     232
# 5  Sample1 2002  354    36     268
# 6  Sample1 2003  354    59     327
# 7  Sample1 2004  354    64     391
# 8  Sample1 2005  354    23     414
# 9  Sample1 2006  354    69     483
# 10 Sample1 2007  354    94     577
# 11 Sample1 2008  354    24     601
# 12 Sample2 1964 1342     7       7
# 13 Sample2 1965 1342    24      31
# 14 Sample3 2002  859    90      90
# 15 Sample3 2003  859    93     183
# 16 Sample3 2004  859    53     236
# 17 Sample3 2005  859    98     334

Здесь я использую by, но есть еще несколько способов вычислить cumsum на уровне факторов

mapply(cumsum, with(d, split(VALUE, NAME)))
sapply(unname(split(d$VALUE, d$NAME)), cumsum)
unsplit(sapply(split(d$VALUE, d$NAME), cumsum), d$NAME) 

Последнее, вероятно, наиболее благоприятно, поскольку в нем отсутствуют названия факторов.

Есть также

library(plyr)
ddply(d, .(NAME), mutate, CUMSUM = cumsum(VALUE))     

Для подмножества более трех наблюдений вы можете использовать простой table

t <- table(d$NAME)
ss <- d[d$NAME %in% names(t)[t > 3], ]

Затем, чтобы записать его в файл с

write.table(ss, "filename", sep = ";")
person Rich Scriven    schedule 02.08.2014
comment
Вы можете добавить transform(d, CUMRAIN = ave(VALUE, NAME, FUN = cumsum)) в свою коллекцию методов. - person talat; 03.08.2014
comment
Я оставлял тебе кое-что. :) - person Rich Scriven; 03.08.2014
comment
Спасибо за ответы на все вопросы! Однако, если я запишу таблицу в файл, как вы предложили, порядок элементов будет неправильным. ИМЯ ГОД ИД ЗНАЧЕНИЕ ОБОГНОВАНИЕ 1 Образец1 1998 354 45 45 2 Образец1 1999 354 23 68 3 Образец1 2000 354 66 134 и так далее… как мне получить все заголовки столбцов на один шаг вправо, чтобы они были правильными (это важно для дальнейшей обработки данных в моем скрипте!) - person kurdtc; 03.08.2014
comment
извините за ужасное форматирование: здесь вы можете найти получившийся файл .csv: dl.dropboxusercontent. ru / u / 16277659 / test.csv - person kurdtc; 03.08.2014
comment
При записи данных в файл добавьте аргумент row.names = FALSE в функцию write.table. - person talat; 03.08.2014

Вот решение с использованием пакета data.table при условии, что ваши данные хранятся в dat:

require(data.table)
ans = setDT(dat)[, crain := cumsum(VALUE[.N > 3L]), by=NAME][!is.na(crain)]
  • setDT преобразует data.frame в data.table
  • Затем мы группируем по NAME и вычисляем для каждой уникальной группы кумулятивную сумму VALUE для этой группы только, если количество наблюдений для этой группы (= .N, встроенная специальная переменная)> 3L. И мы присваиваем значения новому столбцу crain по ссылке.
  • Поскольку мы не вычисляли cumsum для групп с ‹= 3L наблюдений, в них будет NA значений. Мы используем это для получения желаемого результата.

Теперь вы можете использовать write.table(.) на ans, как показано в других ответах.

Примечание. В этом ответе предполагается, что ваш набор данных, конечно же, не содержит NA значений для VALUE столбца.

person Arun    schedule 02.08.2014

Вот еще один подход с использованием dplyr

library(dplyr)

data %>%                                   # your data frame
  group_by(NAME) %>%                       # the grouping variable. could add more variables if necessary
  filter(n() > 3) %>%                      # n()  calculates the number of rows per group and then only those with more than 3 are filtered (selected)
  mutate(CUMRAIN = cumsum(VALUE)) %>%      # add a new column "CUMRAIN"
  write.table(., "test.csv", sep = ";")    # write the subset to a file. The "." indicates that it uses the output of the previous operations piped by %>%   

Операции объединяются в конвейер с помощью оператора %>%.

Обновление: как указано в ответе @ Arun, нет необходимости рассчитывать совокупный дождь для этой выборки с менее чем 3 наблюдениями, поэтому мы можем сначала использовать операцию фильтра (перед изменением), чтобы создать подмножество со всеми выборками, содержащими более 3 наблюдений а затем вычислить совокупный дождь.

person talat    schedule 02.08.2014