Извините об этом «втором ответе», но у вас действительно было два вопроса ... @ Решение Ананды по перестройке ваших данных чрезвычайно элегантно. Это еще один способ подумать об этом.
Если вы транспонируете входную матрицу, вы получаете новую матрицу, где первый столбец является страной, второй столбец является городом, третий столбец «тип» (из-за отсутствия лучшего термина), а фактические данные в других столбцах (так что для каждого «времени» имеется еще один столбец).
Таким образом, другой подход состоит в том, чтобы перенести сначала, а затем расплавить новую матрицу. Это позволяет избежать создания всех имен конкатенированных столбцов и их последующего разделения. Проблема в том, что melt.data.frame
исключительно неэффективен с очень большим количеством столбцов (которые вы бы здесь). Таким образом, так будет bbe 10X медленнее, чем подход Ананды.
Решение состоит в использовании melt.array
(просто позвоните melt(...)
с массивом, а не с кадром данных). Как показано ниже, этот подход ~ 20X быстрее, с более крупными наборами данных (ваш был 11 МБ).
library(reshape) # for melt(...)
library(microbenchmark) # for microbenchmark(...)
# this is just to model your situation with more realistic size
# create a large data frame (250 columns of country, city, type; 1000 rows of time)
df <- rep(c("USA","UK","FR","CHN","GER"),each=50) # time + 250 columns
df <- rbind(df,rep(c(c("NY","SF","CHI","BOS","LA")),each=10))
df <- rbind(df,rep(c("pork","peas","nuts","fruit","other")))
df <- rbind(df,matrix(sample(1:1000,250*1000,replace=T),ncol=250))
df <- cbind(c("time","","",
as.character(as.Date(1:1000,origin="2010-01-01"))),df)
df <- data.frame(df) # big warning here about duplicated row names; not important
# @Ananda'a approach:
transform.orig <- function(df){
B <- df[-(1:3),]
Bnames <- df[1:3,]
names(B) <- apply(Bnames, 2, function(x) paste(x[x != ""], collapse = "_"))
BL <- melt(B, id.vars="time")
final <- cbind(BL[c("time", "value")],
colsplit(BL$variable, "_",
c("country", "state", "product")))
return(final)
}
# transpose approach:
transform.new <- function(df) {
zz <- t(df)
times <- t(zz[1,4:ncol(zz)])
colnames(zz) <- c("country","city","type", times)
data <- melt(zz[-1,-(1:3)],varnames=c("id","time"))
final <- cbind(country=rep(zz[-1,1],each=ncol(zz)-3),
city =rep(zz[-1,2],each=ncol(zz)-3),
type =rep(zz[-1,3],each=ncol(zz)-3),
data[,-1])
return(final)
}
# benchmark
microbenchmark(transform.orig(df),transform.new(df), times=5, unit="s")
Unit: seconds
expr min lq median uq max neval
transform.orig(df) 9.2511679 9.6986330 9.889457 10.1518191 10.3354328 5
transform.new(df) 0.4383197 0.4724145 0.474212 0.5815531 0.6886383 5
Так вы спрашиваете о чтении данных или изменении данных после того, как вы это сделали? – A5C1D2H2I1M1N2O1R2T1
Я думаю, что оба они, я все еще пытаюсь получить R, чтобы прочитать книгу, не сказав, что ее нехватка памяти, также спасибо за редактирование сообщения, это мой первый вопрос, задающий вопрос. – BaconDoggie
вы пробовали 'read.xls' в пакете' gdata'? Я думаю, что 11 МБ-файл не должен быть проблемой. – sparrow