2015-10-09 2 views
7

Добавление столбца в объект xts является простым, если вы знаете имя столбца раньше времени. Например, чтобы добавить столбец с именем «Ъ»:Динамическое добавление столбца в объект xts

n <- 5 
x <- merge(xts(order.by = as.Date('2015-1-1') + 1:n), a = rnorm(n)) 
x$b <- rnorm(n) 

Добавление динамически с именем столбца (т.е. столбец, имя которого известно только во время выполнения) сложнее:

new.col.name <- 'c' # known only at runtime 
x[, new.col.name] <- rnorm(n) # this generates an error 

Один подход заключается в том, чтобы добавить столбец с временным именем и затем переименовать его:

stopifnot(!('tmp' %in% names(x))) 
x$tmp <- rnorm(n) 
names(x)[names(x) == 'tmp'] <- new.col.name 

Есть ли лучший способ сделать это? (Кроме того, не приписывая names найденного объекта XTS в экземпляре объекта делается? Так, например, будет Изложенными выше подход хорошо работать, если n были очень большими?)

ответ

8

Самого простым/ясным, что нужно сделать слияние исходного объекта с новым столбцом (-ами), после преобразования нового столбца (ов) в матрицу (так что вы можете установить имя столбца).

set.seed(21) 
newData <- rnorm(n) 
x1 <- merge(x, matrix(newData, ncol=1, dimnames=list(NULL, new.col.name))) 
# another way to do the same thing 
dim(newData) <- c(nrow(x), 1) 
colnames(newData) <- new.col.name 
x2 <- merge(x, newData) 

Чтобы ответить на ваш второй вопрос: да, присвоение имен (и COLNAMES) на объекте XTS создает копию. Вы можете видеть это, используя tracemem и вывод от gc.

> R -q # new R session 
R> x <- xts::.xts(1:1e6, 1:1e6) 
R> tracemem(x) 
[1] "<0x2892400>" 
R> gc() 
      used (Mb) gc trigger (Mb) max used (Mb) 
Ncells 259260 13.9  592000 31.7 350000 18.7 
Vcells 1445207 11.1 4403055 33.6 3445276 26.3 
R> colnames(x) <- "hi" 
tracemem[0x2892400 -> 0x24c1ad0]: 
tracemem[0x24c1ad0 -> 0x2c62d30]: colnames<- 
tracemem[0x2c62d30 -> 0x3033660]: dimnames<-.xts dimnames<- colnames<- 
tracemem[0x3033660 -> 0x3403f90]: dimnames<-.xts dimnames<- colnames<- 
tracemem[0x3403f90 -> 0x37d48c0]: colnames<- dimnames<-.xts dimnames<- colnames<- 
tracemem[0x37d48c0 -> 0x3033660]: dimnames<-.xts dimnames<- colnames<- 
R> gc() 
      used (Mb) gc trigger (Mb) max used (Mb) 
Ncells 259696 13.9  592000 31.7 350000 18.7 
Vcells 1445750 11.1 4403055 33.6 3949359 30.2 
R> print(object.size(x), units="Mb") 
7.6 Mb 

Вы можете увидеть colnames<- вызов вызывает ~ 4 Мб дополнительной памяти для использования (далее «макс (МБ)» увеличился на эту сумму). Весь объект xts составляет ~ 8 МБ, половина из которых равна coredata, а другая половина - index. Таким образом, 4 МБ дополнительной памяти используется для копирования coredata.

Если вы хотите избежать копирования, вы можете установить ее вручную. Но будьте осторожны, потому что вы можете сделать что-то, что в противном случае было бы уловлено «чеками» в colnames<-.xts.

> R -q # new R session 
R> x <- xts::.xts(1:1e6, 1:1e6) 
R> tracemem(x) 
[1] "<0x2cc5330>" 
R> gc() 
      used (Mb) gc trigger (Mb) max used (Mb) 
Ncells 256397 13.7  592000 31.7 350000 18.7 
Vcells 1440915 11.0 4397699 33.6 3441761 26.3 
R> attr(x, 'dimnames') <- list(NULL, "hi") 
tracemem[0x2cc5330 -> 0x28f4a00]: 
R> gc() 
      used (Mb) gc trigger (Mb) max used (Mb) 
Ncells 256403 13.7  592000 31.7 350000 18.7 
Vcells 1440916 11.0 4397699 33.6 3441761 26.3 
R> print(object.size(x), units="Mb") 
7.6 Mb 
1

Я считаю, что нет хорошей альтернативы, но имена столбцов просто атрибут, так дешев изменить, и никаких копий не будут. (EDIT: Uh-oh, только что видели Я, кажется, говорю об обратном к Джошуа .--> См. Обсуждение в комментариях. Кажется, dimnames.xts делает больше, чем просто устанавливает атрибут и предполагает копирование базовых данных, поэтому . будьте осторожны)

вы также можете использовать cbind(), который является синонимом merge.xts, но (AFAIK) не дает никаких преимуществ по методу x$b вы показали:

n <- 5 
x <- merge(xts(order.by = as.Date('2015-1-1') + 1:n), a = rnorm(n)) 
x$b <- rnorm(n) 
x = cbind(x, c = rnorm(n)) 
colnames(x)[3] = "real name" 

Я также показал один из способов для изменения имени столбца. Если вы не знаете, что это третий столбец, тогда общий подход: colnames(x)[length(colnames(x))] = "real name"

+0

Как я уже сказал в своем ответе, установка 'colnames' создает копии. Например: 'x <- .xts (1,1); tracemem (х); colnames (x) <- "hi" ' –

+0

Я редактировал, а вы добавили этот комментарий @JoshuaUlrich. Фактические данные матрицы не копируются? –

+0

Фактические данные матрицы копируются, к сожалению. Я добавил некоторые детали к моему ответу, чтобы продемонстрировать. –

 Смежные вопросы

  • Нет связанных вопросов^_^