Назначение одинаковых имен столбцов / строк многим матрицам в цикле For Loop

У меня есть целый набор матриц, которым я хочу назначить имена столбцов и строк на основе столбца имен, которые хранятся в другом столбце (Names) в имеющемся у меня фрейме данных (месяцы).

Каждая матрица, которой я хочу присвоить имена, соответствует объединенной "партнерской" строке и метрике, хранящейся здесь, например одна из матриц называется facebook_Total_Completed_Rentals:

Metrics = c('_Total_Completed_Rentals','_Registered_Completed_rentals',
'_Registered_renters','_New_Registrations')

Partners = c('facebook', 'altrooz', 'adperio', 'snapchat', 'apple', 'google')    

Я хочу пройти через эти два цикла, чтобы присвоить имена матрицам таким образом, чтобы избежать необходимости вручную кодировать все операторы colnames и row.names:

for(i in 1:length(Metrics)){
  for(j in 1:length(Partners)){
  temp = paste0(Partners[j],Metrics[i])
  colnames(temp)= months$Names[1:(months_cut-1)]
  row.names(temp) = months$Names[1:(months_cut-1)]
  }
}  

Но получаю ошибку:

Error in `colnames<-`(`*tmp*`, value = months$Names[1:(months_cut - 1)]) : 
attempt to set 'colnames' on an object with less than two dimensions

Пожалуйста помоги


person Keith    schedule 27.11.2018    source источник
comment
По сути, вам нужно использовать get для возврата объекта среды по имени. Попробуйте tmp_matrix <- get(temp) внутри цикла, поскольку temp - это символьное значение, а не фактический объект матрицы. Но в идеале вы сохраняете все похожие структурированные матрицы в списке, а не как отдельные объекты, и вызываете его по списку и его имени: list$facebook_Total_Completed_Rentals.   -  person Parfait    schedule 27.11.2018


Ответы (2)


Рассмотрим следующие данные фреймов:

iris_a  <- iris[1:2,]
iris_b  <- iris[3:4,]
iris_c  <- iris[5:6,]

Чистый способ сделать то, что вы хотите, - это поместить их в список и применить к нему изменения:

rnms <- c("foo","bar")
your_list <- lapply(list(iris_a = iris_a,iris_b = iris_b, iris_c = iris_c), function(x){
  rownames(x) <- rnms
  x
})

Затем, если необходимо, вы можете извлечь его элементы обратно в свою локальную среду:

list2env(your_list, environment())
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# foo          5.1         3.5          1.4         0.2  setosa
# bar          4.9         3.0          1.4         0.2  setosa

Немного компактнее, используя tidyverse:

your_list <- map(lst(iris_a, iris_b, iris_c), `rownames<-`, rnms)
person Moody_Mudskipper    schedule 27.11.2018
comment
а если бы матрицы были разных размеров? - person M--; 27.11.2018
comment
Тогда вы не сможете дать им одинаковые имена измерений. - person Milan Valášek; 27.11.2018
comment
Немного компактнее, используя base: your_list <- lapply(mget(ls(pattern="iris_")), "row.names<-", rnms) - person Parfait; 27.11.2018
comment
@Parfait, но OP не имеет шаблона в его реальных данных :) - person Moody_Mudskipper; 27.11.2018
comment
Вместо ls() можно было поставить что-нибудь вроде apply(expand.grid(Partners, Metrics), 1, paste, collapse = "") - person Milan Valášek; 27.11.2018
comment
Или используйте outer: all_matrices <- as.vector(outer(Partners, Metrics, paste0)) и передайте all_matrices в mget. - person Parfait; 27.11.2018
comment
Прочитал вопрос немного быстро, вижу, что не на все отвечаю. Насколько я понимаю, структура данных предполагает, что OP должен иметь список списка или, возможно, даже один фрейм данных с соответствующими дополнительными столбцами. Так что я бы посоветовал разобраться во всем выше по течению, а не взламывать их сейчас. - person Moody_Mudskipper; 27.11.2018

Хотя ответ @Moody, вероятно, является более чистым вариантом, я подумал, что предоставлю код, который делает то, что вы изначально хотели:

Создадим 4 матрицы, названия которых представляют собой комбинации двух элементов:

a_1 <- a_2 <- b_1 <- b_2 <- matrix(1:20, ncol = 5)

Вектор имен строк и имен столбцов:

rnames <- paste0("row_", 1:4)
cnames <- paste0("col_", 1:5)

Получите элементы имени:

x <- c("a", "b")
y <- 1:2

Для вашего цикла вы должны понимать, что temp - это просто строка символов, поэтому colnames(temp) не будет работать. Вы хотите создать строку, включающую всю команду, проанализировать ее как выражение, а затем оценить ее:

for (i in x) {
  for (j in y) {
    temp <- paste(i, j, sep = "_")
    eval(parse(text = paste0("dimnames(", temp, ") <- list(rnames, cnames)")))
  }
}

Примечание. dimnames(temp) быстрее, чем rownames и colnames.

person Milan Valášek    schedule 27.11.2018