2013-07-23 3 views
2

У меня есть кадр данных с одним столбцом и 158112 разных значений. Значения не упорядочены случайным образом. Каждые 24 значения представляют один день. Каждый день указан 18 раз, а следующий - на следующий день, например. 18x24 для 01.01.2012, 18x24 для 02.01.2012 и так далее.Реорганизация кадра данных

 df 
1  593 
2  939 
3  734 
4  791 
5  184 
6  495 
... 
158112 683 

Я хочу организовать их в новом фрейме данных в другой структуре. Процесс будет выглядеть примерно так:

Возьмите первые 24 значения и поместите их в новый фрейм данных «new_df» column no. 1, возьмите следующие 24 значения и поместите в столбец «new_df» №. 2, возьмите следующие 24 значения и поместите в столбец «new_df» no. 3. Сделайте это до тех пор, пока 18 столбцов не будут заполнены с каждым 24 значениями, а затем снова начните с колонки №1 и добавьте следующие 24 значения и т. Д. Итак, в конце я хотел бы иметь «new_df» с 18 столбцами и 8784 строки.

Любые идеи?

ответ

1

Я думаю, что вы хотите что-то вроде следующего:

# sample data 
mydf <- data.frame(df=rnorm(18*8784,0,1)) 
# split dataframe into chunks (of 18*24) 
mylist <- split(mydf,rep(1:366,each=432)) 
# turn each chunk into a matrix of the right shape and `rbind` them back together 
new_df <- do.call(rbind, lapply(mylist, function(x) matrix(x[,1],nrow=24))) 

Вы можете проверить, если это правильно с:

all.equal(mydf[1:24,1],new_df[1:24,1]) # first 24 values are first column 
all.equal(mydf[25:48,1],new_df[1:24,2]) # next 24 values are second column 
all.equal(mydf[433:456,1],new_df[25:48,1]) # day 2 starts in the first column 

Все те должны be TRUE. И я думаю, вы хотите, чтобы это как data.frame, поэтому просто используйте as.data.frame(new_df), чтобы вернуть результат в файл data.frame.

+0

+1 для точности того, что запросил ОП; однако вы также должны изучить 'array' для обработки расщепления, как я сделал [здесь] (http://stackoverflow.com/a/17816070/1270695). – A5C1D2H2I1M1N2O1R2T1

+0

Спасибо. Я только начинаю знаком с 'array', и ваше решение выглядит гладким. Это также более эффективно? – Thomas

+0

, если OP останавливается при создании этапа «array» в моем ответе, он должен * быть довольно быстрым. R работает быстрее на матрицах, чем на 'data.frame', поэтому я предполагаю, что то же самое относится к' array'. На последнем этапе, где я конвертирую (* снова *) в «xts», результирующий объект «xts» хранит данные как «матрицу», которая более эффективна, чем 'data.frame'. – A5C1D2H2I1M1N2O1R2T1

2

Попробуйте это:

set.seed(1) 
df <- data.frame(df=sample(1:999, 158112, TRUE)) # creating some data 
new_df <- data.frame(matrix(unlist(df), ncol=18)) # putting df into a 8784 x 18 data.frame 
dim(new_df) # checking the dimensions of new_df 
+0

Я согласен (и был так же думая о 'df <- data.frame (x = seq (158112)), new_df <- do.call (rbind, tapply (df [, 1], rep (seq (366), each = 18 * 24), matrix , ncol = 18)) ') ... – texb

+0

То не совсем то, что я хочу. Исходный кадр данных не упорядочен случайным образом. Он представляет каждый день 2012 года ежечасно, но каждый день 18 раз с разными значениями каждый раз. –

+0

@Henning_FL эта информация должна быть в вашем вопросе, чтобы сделать ее более ясной, иначе я предполагаю некоторый контекст, чтобы дать ответ. Помните, что качество ответов тесно связано с качеством вопросов. –

1

Возможно, лучше, чем альтернативы до сих пор, использовать array для управления вашими данными в желаемую структуру. Поскольку вы просто имеете дело с одним вектором и хотите заполнить свои данные столбцами, вам просто нужно назначить dim s вашему вектору.

Вот упрощенный пример. Начну с вектором длиной 40.

mydata <- rep(1:8, each = 5) 
mydata 
# [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 
# [21] 5 5 5 5 5 6 6 6 6 6 7 7 7 7 7 8 8 8 8 8 

Теперь представьте, что мы хотим, чтобы преобразовать это в четырех колонок, где первые 20 значений группируются вместе, а вторые 20 значений сгруппированы вместе. (В ваших данных, было бы первые 24 * 18 значения группируются вместе, чтобы представить 18 столбцов записей на один день.)

Вот как бы это сделать:

myarray <- array(mydata, dim=c(5, 4, 2), 
       dimnames = list(NULL, NULL, 
           c("2012-01-01", "2012-01-02"))) 
myarray 
# , , 2012-01-01 
# 
#  [,1] [,2] [,3] [,4] 
# [1,] 1 2 3 4 
# [2,] 1 2 3 4 
# [3,] 1 2 3 4 
# [4,] 1 2 3 4 
# [5,] 1 2 3 4 
# 
# , , 2012-01-02 
# 
#  [,1] [,2] [,3] [,4] 
# [1,] 5 6 7 8 
# [2,] 5 6 7 8 
# [3,] 5 6 7 8 
# [4,] 5 6 7 8 
# [5,] 5 6 7 8 

Может быть, вы хотите, чтобы остановить с этой точки зрения. Однако, если вы хотите пройти весь путь до одного data.frame, это также легко возможно.

Использование @ выборочных данных Жильбер просто в целях облегчения репликации:

set.seed(1) 
df <- data.frame(df=sample(1:999, 158112, TRUE)) 
# Hopefully you've done your math correctly 
# R will recycle if the dims aren't correct 
# for your data. 
Ndays <- nrow(df)/(24*18) 
dfarray <- array(df$df, 
       dim = c(24, 18, Ndays), 
       # Add dimnames by creating a date sequence 
       dimnames = list(NULL, NULL, as.character(
        seq(as.Date("2012-01-01"), by = "1 day", 
         length.out = Ndays)))) 
# Use `apply` to convert this to a `list` of `data.frame`s 
temp <- apply(dfarray, 3, as.data.frame) 
# Use `lapply` to create your intermediate `data.frame`s 
out <- lapply(names(temp), function(x) { 
    data.frame(date = as.Date(x), temp[[x]]) 
}) 
# Use `do.call(rbind, ...)` to get your final `data.frame` 
final <- do.call(rbind, out) 

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

head(final) 
#   date V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 
# 1 2012-01-01 266 267 732 347 455 991 729 724 101 649 307 702 133 841 443 
# 2 2012-01-01 372 386 693 334 410 496 453 338 927 953 578 165 222 720 157 
# 3 2012-01-01 573 14 478 476 811 484 175 630 283 953 910 65 227 267 582 
# 4 2012-01-01 908 383 861 892 605 174 746 840 590 340 143 754 132 495 970 
# 5 2012-01-01 202 869 438 864 655 755 105 856 111 263 415 620 981 84 989 
# 6 2012-01-01 898 341 245 390 353 454 864 391 840 166 211 170 327 354 177 
# V16 V17 V18 
# 1 109 232 12 
# 2 333 241 940 
# 3 837 797 993 
# 4 277 831 358 
# 5 587 114 747 
# 6 836 963 793 

Я до сих пор сильно предположим, что вы знакомы с пакетом «xts», если вы собираетесь делать много работы с данными временных рядов.

Переход от «окончательное» data.frame выше к xts объекта легко:

library(xts) 
Final <- xts(final[-1], order.by=final[[1]]) 

И это позволит вам легко делать забавные вещи, как это:

apply.quarterly(Final, mean) 
#     V1  V2  V3  V4  V5  V6 
# 2012-03-31 490.5256 493.8338 507.4272 503.5421 495.0929 494.4025 
# 2012-06-30 511.5792 508.1493 500.9043 500.2152 509.0614 499.9881 
# 2012-09-30 496.2672 501.1399 496.3542 493.7423 504.8170 507.1671 
# 2012-12-31 503.9583 502.5616 502.8936 509.2120 503.2387 502.4678 
#     V7  V8  V9  V10  V11  V12 
# 2012-03-31 490.2477 492.2115 510.6525 499.8168 506.9510 494.3654 
# 2012-06-30 494.0962 497.0357 506.9267 500.2198 501.4263 494.1117 
# 2012-09-30 509.9561 487.0543 497.2206 485.4511 498.1191 494.5190 
# 2012-12-31 503.0095 500.7903 494.7428 494.1409 502.0181 496.9764 
#     V13  V14  V15  V16  V17  V18 
# 2012-03-31 504.4130 499.8581 503.0023 501.0137 499.1021 504.7711 
# 2012-06-30 500.0504 501.2903 490.7582 502.7395 503.5737 496.4821 
# 2012-09-30 493.4860 499.2088 500.7260 503.1907 491.9583 490.4293 
# 2012-12-31 500.4348 507.9475 499.3637 486.4438 496.8220 492.8890 
Смежные вопросы