Как скопировать атрибуты из одного фрейма данных в другой или переназначить атрибуты только что транспонированному фрейму данных — R

#r #attr #purrr #reshape2 #tidyselect

#r #attr #мурлыканье #изменение формы 2 #аккуратный выбор

Вопрос:

После переноса данных я хотел бы переназначить атрибуты, которые были удалены. Это также может быть применимо к копированию атрибутов из одного фрейма данных в другой. Или копирование атрибутов после мутирования и т.д., Когда они удалены.

  library(reshape2)

 df <- data.frame(id = c(1,2,3,4,5), 
                  time = c(11, 22,33,44,55),
                  c  = c(1,2,3,5,5),
                  d = c(4,2,5,4,NA))

attr(df$id,"label")<- "label"
attr(df$time,"label")<- "label2"
attr(df$c,"label")<- "something here"
attr(df$d,"label")<- "count of something"
str(df)

 str(df)
 data.frame':   5 obs. of  4 variables:
 $ id  : num  1 2 3 4 5
  ..- attr(*, "label")= chr "label"
 $ time: num  11 22 33 44 55
  ..- attr(*, "label")= chr "label2"
 $ c   : num  1 2 3 5 5
  ..- attr(*, "label")= chr "something here"
 $ d   : num  4 2 5 4 NA
  ..- attr(*, "label")= chr "count of something"
  

Приведение к wide

 dfwide<- recast(df,id~variable  time, 
            id.var = c("id","time"))
  

Обычное сообщение о потере атрибута:

    Warning message:
     attributes are not identical across measure variables; they will be dropped 

 str(dfwide)
'data.frame':   5 obs. of  11 variables:
 $ id  : num  1 2 3 4 5
 $ c_11: num  1 NA NA NA NA
 $ c_22: num  NA 2 NA NA NA
 $ c_33: num  NA NA 3 NA NA
 $ c_44: num  NA NA NA 5 NA
 $ c_55: num  NA NA NA NA 5
 $ d_11: num  4 NA NA NA NA
 $ d_22: num  NA 2 NA NA NA
 $ d_33: num  NA NA 5 NA NA
 $ d_44: num  NA NA NA 4 NA
 $ d_55: num  NA NA NA NA NA
  

С помощью mostattributes можно копировать атрибуты между фреймами данных, но для итераций по многим именам столбцов я не могу понять или подумать о том, как эффективно сопоставить это другим способом, за исключением одного за другим.

  mostattributes(dfwide$c_11)<-attributes(df$c)
 mostattributes(dfwide$c_22)<-attributes(df$c)
 > str(dfwide)
 'data.frame':  5 obs. of  11 variables:
  $ id  : num  1 2 3 4 5
  $ c_11: num  1 NA NA NA NA
  ..- attr(*, "label")= chr "something here"
  $ c_22: num  NA 2 NA NA NA
  ..- attr(*, "label")= chr "something here"
  $ c_33: num  NA NA 3 NA NA
  

Я пытался автоматизировать это, но потерпел неудачу (все c должны иметь одинаковые метки, а d — одинаковые метки):

 #extract arguments
dlist<-enframe(names(df))%>%
   slice(-1,-2)%>%
   pull(., value)
 dlist

 dlistw<-enframe(names(dfwide))%>%
  slice(-1)%>%
  pull(., value)
 dlistw

#function
mostatt<- function(var1, var2) {
  mostattributes(dfwide[[var1]])<<-attributes(df[[var2]])
}

mapply(mostatt,dlistw,dlist)
str(dfwide)

'data.frame':   5 obs. of  11 variables:
 $ id  : num  1 2 3 4 5
 $ c_11: num  1 NA NA NA NA
  ..- attr(*, "label")= chr "something here"
 $ c_22: num  NA 2 NA NA NA
  ..- attr(*, "label")= chr "count of something"
 $ c_33: num  NA NA 3 NA NA
  ..- attr(*, "label")= chr "something here"
 $ c_44: num  NA NA NA 5 NA
  ..- attr(*, "label")= chr "count of something"
 $ c_55: num  NA NA NA NA 5
  ..- attr(*, "label")= chr "something here"
 $ d_11: num  4 NA NA NA NA
  ..- attr(*, "label")= chr "count of something"
 $ d_22: num  NA 2 NA NA NA
  ..- attr(*, "label")= chr "something here"
 $ d_33: num  NA NA 5 NA NA
  ..- attr(*, "label")= chr "count of something"
 $ d_44: num  NA NA NA 4 NA
  ..- attr(*, "label")= chr "something here"
 $ d_55: num  NA NA NA NA NA
  ..- attr(*, "label")= chr "count of something"
  

Я думаю, что стоит попробовать использовать tidyselect starts_with , но не уверен, как это включить. Будем признательны за любые предложения. Спасибо!

Ответ №1:

Это вариант:

 for(i in (setdiff(colnames(df), "id"))){
  for(x in colnames(dfwide)[(grepl(i, colnames(dfwide)))])
      mostattributes(dfwide[[x]]) <- attributes(df[[i]])
}
mostattributes(dfwide$id) <- attributes(df$id) 
  

Поскольку d содержится в id , мне нужно переписать id в конце.
Если вы измените d на e , это будет еще проще:

 df <- data.frame(id = c(1,2,3,4,5), 
                 time = c(11, 22,33,44,55),
                 c  = c(1,2,3,5,5),
                 e = c(4,2,5,4,NA))


attr(df$id,"label")<- "label"
attr(df$time,"label")<- "label2"
attr(df$c,"label")<- "something here"
attr(df$e,"label")<- "count of something"
str(df)

dfwide<- recast(df,id~variable  time, 
                id.var = c("id","time"))

for(i in (colnames(df))){
  for(x in colnames(dfwide)[(grepl(i, colnames(dfwide)))])
    mostattributes(dfwide[[x]]) <- attributes(df[[i]])
}
  

Комментарии:

1. Это хороший вариант. Спасибо, что поделились. Я не представлял, что можно использовать grep / grepl подобным образом. Интересно, есть ли способ добавить регулярное выражение carat ^ к инструкции, чтобы обозначить начальную позицию шаблона. Я поиграю с этим. Но на данный момент это решение работает для меня, потому что имена столбцов в фреймах данных, которые у меня есть, намного длиннее, и grepl будет работать с этими строками вместо одного символа. Еще раз спасибо!