Сортировка фрейма данных по формату месяц-год - PullRequest
4 голосов
/ 04 января 2011

Я борюсь с чем-то очень простым: сортировка фрейма данных по формату времени (месяц-год или, в данном случае, «% B-% y»). Моя цель - рассчитать различную ежемесячную статистику, начиная с суммы.

Часть соответствующей части фрейма данных выглядит следующим образом * (Это идет хорошо и соответствует моей цели. Я включаю ее здесь, чтобы показать, откуда возникла проблема ) *:

> tmp09
   Instrument AccountValue   monthYear   ExitTime
1         JPM         6997    april-07 2007-04-10
2         JPM         7261      mei-07 2007-05-29
3         JPM         7545     juli-07 2007-07-18
4         JPM         7614     juli-07 2007-07-19
5         JPM         7897 augustus-07 2007-08-22
10        JPM         7423 november-07 2007-11-02
11        KFT         6992      mei-07 2007-05-14
12        KFT         6944      mei-07 2007-05-21
13        KFT         7069     juli-07 2007-07-09
14        KFT         6919     juli-07 2007-07-16
# Order on the exit time, which corresponds with 'monthYear'
> tmp09.sorted <- tmp09[order(tmp09$ExitTime),]
> tmp09.sorted
   Instrument AccountValue   monthYear   ExitTime
1         JPM         6997    april-07 2007-04-10
11        KFT         6992      mei-07 2007-05-14
12        KFT         6944      mei-07 2007-05-21
2         JPM         7261      mei-07 2007-05-29
13        KFT         7069     juli-07 2007-07-09
14        KFT         6919     juli-07 2007-07-16
3         JPM         7545     juli-07 2007-07-18
4         JPM         7614     juli-07 2007-07-19
5         JPM         7897 augustus-07 2007-08-22
10        JPM         7423 november-07 2007-11-02

Пока все хорошо, сортировка по ExitTime работает. Проблема начинается, когда я пытаюсь вычислить итоги за месяц, после чего следует попытка отсортировать этот вывод :

# Calculate the total results per month
> Tmp09Totals <- tapply(tmp09.sorted$AccountValue, tmp09.sorted$monthYear, sum)
> Tmp09Totals <- data.frame(Tmp09Totals)
> Tmp09Totals
            Tmp09Totals
april-07           6997
augustus-07        7897
juli-07           29147
mei-07            21197
november-07        7423

Как отсортировать этот вывод в хронологическом порядке?

Я уже пробовал (помимо различных попыток конвертировать monthYear в другой формат даты): порядок, сортировка, sort.list, sort_df, изменение формы и вычисление суммы на основе tapply, lapply, sapply, aggregate. И даже переписать имена строк (указав им число от 1 до длины (tmp09.sorted2$AccountValue)) не получилось. Я также пытался присвоить каждому месяцу-году разные идентификаторы на основе того, что я узнал в другом вопросе, но R также испытывал трудности в различении значений месяца и года.

Правильный порядок вывода будет april-07,mei-07,juli-07,augustus07, november-07:

apr-07  6997
mei-07  21197
jul-07  29147
aug-07  7897
nov-07  7423

Ответы [ 6 ]

9 голосов
/ 04 января 2011

Было бы проще иметь отдельные Month и Year факторы в правильном порядке и использовать tapply для объединения обеих переменных, например:

## The Month factor
tmp09 <- within(tmp09,
                Month <- droplevels(factor(strftime(ExitTime, format = "%B"),
                                                    levels = month.name)))
## for @Jura25's locale, we can't use the in built English constant
## instead, we can use this solution, from ?month.name:
## format(ISOdate(2000, 1:12, 1), "%B"))
tmp09 <- within(tmp09,
                Month <- droplevels(factor(strftime(ExitTime, format = "%B"),
                                                    levels = format(ISOdate(2000, 1:12, 1), "%B"))))
##
## And the Year factor
tmp09 <- within(tmp09, Year <- factor(strftime(ExitTime, format = "%Y")))

, что дает нам(в моем регионе):

> head(tmp09)
   Instrument AccountValue   monthYear   ExitTime    Month Year
1         JPM         6997    april-07 2007-04-10    April 2007
2         JPM         7261      mei-07 2007-05-29      May 2007
3         JPM         7545     juli-07 2007-07-18     July 2007
4         JPM         7614     juli-07 2007-07-19     July 2007
5         JPM         7897 augustus-07 2007-08-22   August 2007
10        JPM         7423 november-07 2007-11-02 November 2007

Затем используйте tapply с обоими факторами:

> with(tmp09, tapply(AccountValue, list(Month, Year), sum))
          2007
April     6997
May      21197
July     29147
August    7897
November  7423

или через aggregate:

> with(tmp09, aggregate(AccountValue, list(Month = Month, Year = Year), sum))
     Month Year     x
1    April 2007  6997
2      May 2007 21197
3     July 2007 29147
4   August 2007  7897
5 November 2007  7423
4 голосов
/ 05 января 2011

Попробуйте использовать класс "yearmon" в зоопарке, так как он сортируется соответствующим образом.Ниже мы создаем образец фрейма данных DF, а затем добавляем столбец YearMonth класса "yearmon".Наконец мы выполняем нашу агрегацию.Фактическая обработка - это только две последние строки (другая часть предназначена только для создания образца фрейма данных).

Lines <-   "Instrument AccountValue   monthYear   ExitTime
JPM         6997    april-07 2007-04-10
JPM         7261      mei-07 2007-05-29
JPM         7545     juli-07 2007-07-18
JPM         7614     juli-07 2007-07-19
JPM         7897 augustus-07 2007-08-22
JPM         7423 november-07 2007-11-02
KFT         6992      mei-07 2007-05-14
KFT         6944      mei-07 2007-05-21
KFT         7069     juli-07 2007-07-09
KFT         6919     juli-07 2007-07-16"
library(zoo)
DF <- read.table(textConnection(Lines), header = TRUE)

DF$YearMonth <- as.yearmon(DF$ExitTime)
aggregate(AccountValue ~ YearMonth + Instrument, DF, sum)

Это дает следующее:

> aggregate(AccountValue ~ YearMonth + Instrument, DF, sum)
  YearMonth Instrument AccountValue
1  Apr 2007        JPM         6997
2  May 2007        JPM         7261
3  Jul 2007        JPM        15159
4  Aug 2007        JPM         7897
5  Nov 2007        JPM         7423
6  May 2007        KFT        13936
7  Jul 2007        KFT        13988

Несколько иной подходи вывод использует read.zoo напрямую.Он производит один столбец на инструмент и одну строку в год / месяц.Мы читаем в столбцах, присваивая им соответствующие классы, используя "NULL" для столбца monthYear, поскольку мы не будем его использовать.Мы также указываем, что индекс времени - это 3-й столбец оставшихся столбцов, и мы хотим, чтобы входные данные были разделены на столбцы по 1-му столбцу.FUN=as.yearmon указывает, что мы хотим, чтобы индекс времени был преобразован из класса "Date" в класс "yearmon", и мы объединяем все, используя sum.

z <- read.zoo(textConnection(Lines),  header = TRUE, index = 3, 
     split = 1, colClasses = c("character", "numeric", "NULL", "Date"),
     FUN = as.yearmon, aggregate = sum)

Полученный объект зоопарка выглядит следующим образом:

> z
           JPM   KFT
Apr 2007  6997    NA
May 2007  7261 13936
Jul 2007 15159 13988
Aug 2007  7897    NA
Nov 2007  7423    NA

Мы можем предпочесть сохранить его как объект зоопарка, чтобы воспользоваться другими функциями в зоопарке, или мы можем преобразовать его во фрейм данных, например так: data.frame(Time = time(z), coredata(z)), который делает время отдельным столбцом или as.data.frame(z), который использует имена строк для времени.fortify.zoo()z) тоже работает.

3 голосов
/ 04 января 2011

Вы можете изменить порядок уровней факторов с помощью функции reorder.

tmp09$monthYear <- reorder(tmp09$monthYear, as.numeric(as.Date(tmp09$ExitTime)))

Хитрость заключается в том, чтобы использовать числовое представление даты в виде количества дней с 1970-01-01 (см. ?Date) и использовать его среднее значение в качестве ссылки.

1 голос
/ 04 января 2011

Похоже, основная проблема заключается в том, как отсортировать последовательность строк месяц-год в хронологическом порядке.Самый простой способ состоит в том, чтобы предварительно считать «01» в начале каждой строки месяца-года и сортировать их как обычные даты.Итак, возьмите ваш окончательный фрейм данных Tmp09Totals и сделайте следующее:

monYear <- rownames(Tmp09Totals)
sortedMonYear <- format(sort( as.Date( paste('01-', monYear, sep = ''),
                                       '%d-%B-%y')), 
                       '%B-%y')
Tmp09Totals[ sortedMonYear, , drop = FALSE]
1 голос
/ 04 января 2011

Редактировать: Сначала я неправильно понял вопрос. Сначала скопируйте данные, приведенные в вопросе, затем

> tmp09 <- read.table(file="clipboard", header=TRUE)
> Sys.setlocale(category="LC_TIME", locale="Dutch_Belgium.1252")
[1] "Dutch_Belgium.1252"

# create POSIXlt variable from monthYear
> tmp09$d <- strptime(paste("2007", tmp09$monthYear, sep="-"), "%Y-%B-%d")

# create ordered factor
> tmp09$dFac <- droplevels(cut(tmp09$d, breaks="month", ordered=TRUE))
> tmp09[order(tmp09$d), ]
   Instrument AccountValue   monthYear   ExitTime          d       dFac
1         JPM         6997    april-07 2007-04-10 2007-04-07 2007-04-01
2         JPM         7261      mei-07 2007-05-29 2007-05-07 2007-05-01
11        KFT         6992      mei-07 2007-05-14 2007-05-07 2007-05-01
12        KFT         6944      mei-07 2007-05-21 2007-05-07 2007-05-01
3         JPM         7545     juli-07 2007-07-18 2007-07-07 2007-07-01
4         JPM         7614     juli-07 2007-07-19 2007-07-07 2007-07-01
13        KFT         7069     juli-07 2007-07-09 2007-07-07 2007-07-01
14        KFT         6919     juli-07 2007-07-16 2007-07-07 2007-07-01
5         JPM         7897 augustus-07 2007-08-22 2007-08-07 2007-08-01
10        JPM         7423 november-07 2007-11-02 2007-11-07 2007-11-01

> Tmp09Totals <- tapply(tmp09$AccountValue, tmp09$dFac, sum)
> Tmp09Totals
2007-04-01 2007-05-01 2007-07-01 2007-08-01 2007-11-01 
      6997      21197      29147       7897       7423
0 голосов
/ 09 декабря 2015

Старая запись, но достойная подхода data.table:

Чтение данных и установка локальных данных, как описано в @ caracal

> Sys.setlocale(category="LC_TIME", locale="Dutch_Belgium.1252")
[1] "Dutch_Belgium.1252"
> tmp09 <- read.table(file="clipboard", header=TRUE)
> tmp09$ExitTime <- as.Date(tmp09$ExitTime)

Суммирование данных по запросу

require(data.table)
> data.table(tmp09)[, 
+                   .(Tmp09Total = sum(AccountValue)),
+                   by = .(Date = format(ExitTime, "%B-%y"))]
          Date Tmp09Total
1:    april-07       6997
2:      mei-07      21197
3:     juli-07      29147
4: augustus-07       7897
5: november-07       7423
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...