0

Basically i have two dataframes and i want to transfer the attributes of each variable of one to the other dataframe that has the same variables but with null attributes (none). Let me know thnks

attributes(egresados$q0001)<-attributes(egresados_atr$q0001)
attributes(egresados$q0002)<-attributes(egresados_atr$q0002)
attributes(egresados$q0003)<-attributes(egresados_atr$q0003)
attributes(egresados$q0004)<-attributes(egresados_atr$q0004)
attributes(egresados$q0005_0001)<-attributes(egresados_atr$q0005_0001)
attributes(egresados$q0005_0002)<-attributes(egresados_atr$q0005_0002)
attributes(egresados$q0005_0003)<-attributes(egresados_atr$q0005_0003)
attributes(egresados$q0005_0004)<-attributes(egresados_atr$q0005_0004)
attributes(egresados$q0005_0005)<-attributes(egresados_atr$q0005_0005)
attributes(egresados$q0005_0006)<-attributes(egresados_atr$q0005_0006)
attributes(egresados$q0005_0007)<-attributes(egresados_atr$q0005_0007)
attributes(egresados$q0006_0001)<-attributes(egresados_atr$q0006_0001)
attributes(egresados$q0006_0002)<-attributes(egresados_atr$q0006_0002)
attributes(egresados$q0006_0003)<-attributes(egresados_atr$q0006_0003)
attributes(egresados$q0006_0004)<-attributes(egresados_atr$q0006_0004)
attributes(egresados$q0007)<-attributes(egresados_atr$q0007)
attributes(egresados$q0008)<-attributes(egresados_atr$q0008)
attributes(egresados$q0009_0001)<-attributes(egresados_atr$q0009_0001)
attributes(egresados$q0009_0002)<-attributes(egresados_atr$q0009_0002)
attributes(egresados$q0009_0003)<-attributes(egresados_atr$q0009_0003)
attributes(egresados$q0009_0004)<-attributes(egresados_atr$q0009_0004)
attributes(egresados$q0010_0001)<-attributes(egresados_atr$q0010_0001)
attributes(egresados$q0011_0001)<-attributes(egresados_atr$q0011_0001)
attributes(egresados$q0012)<-attributes(egresados_atr$q0012)
attributes(egresados$q0013_0001)<-attributes(egresados_atr$q0013_0001)
attributes(egresados$q0014)<-attributes(egresados_atr$q0014)

I'm using tidyverse and rio packages in my stuggle and i know the functions gather_attrs and spread_attrs i think may help but yet don't know how....

zx8754
  • 52,746
  • 12
  • 114
  • 209

3 Answers3

3

You could do this with a for loop on names (no need to rely on names being in the same order).

for (s in names(egresados)) {
  attributes(egresados[[s]]) <- attributes(egresados_atr[[s]])
}
  • Genius. I've been stuck like one month in this, sometimes better trust the experts. Though at the beggining i run the function and my df egresados turn into a list, then i re-run the function again and it worked. Best wishes Jean-Claude – Santiago Sotelo Jul 06 '21 at 14:40
1

You can try the following with Map -

egresados[] <- Map(function(x, y) {attributes(x) <- attributes(y);x}, 
    egresados, egresados_atr[names(egresados)])
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Hello Ronak thanks for the quick response. I found that your solution quite don't solve my problem, because it turns my dataframe (df) "egresados" into a list. Let me give more info to solve the problem. I have this df 1: `colnames(prueba1)` `[1] "CollectorNm" "q0001" "q0002" "q0002_other"` and df2 with the same variables. The `attributes(prueba1$q0001)` are: `$label [1] "Hecha esta aclaración, ¿desea continuar con la encuesta?" $format.spss [1] "F8.2" $labels Sí No 1 2 ` How can i pass each variable attributes to variables of df2 without reapeting above for each – Santiago Sotelo Jul 06 '21 at 05:21
  • 1
    I added `[]` in the answer to keep the dataframe structure. Does that help? – Ronak Shah Jul 06 '21 at 05:24
0

Assuming that they are are sorted in the same order, then you can use the following:

# create some data as an example
egresados <- setNames(as.list(1:14), sprintf("q%04d", 1:14))
egresados_atr <- setNames(as.list(letters[1:14]), sprintf("q%04d", 1:14))
for(i in 1:length(egresados_atr))
  attributes(egresados_atr[[i]]) <- list(value = egresados_atr[[i]], 
                                         x = 1)

# get the result
res_1 <- Map(
  function(value, other) do.call(structure, c(list(value), attributes(other))), 
  value = egresados, other = egresados_atr)
str(head(res_1, 3)) # show the result for the first three values
#R> List of 3
#R>  $ q0001: int 1
#R>   ..- attr(*, "value")= chr "a"
#R>   ..- attr(*, "x")= num 1
#R>  $ q0002: int 2
#R>   ..- attr(*, "value")= chr "b"
#R>   ..- attr(*, "x")= num 1
#R>  $ q0003: int 3
#R>   ..- attr(*, "value")= chr "c"
#R>   ..- attr(*, "x")= num 1

# in R 4.1.0 or greater                   
res_2 <- Map(c, lapply(egresados, list), lapply(egresados_atr, attributes)) |> 
  lapply(do.call, what = structure)

# they give the same
all.equal(res_1, res_2)
#R> [1] TRUE

The first answer is though quite close to Ronak Shah's answer but uses do.call and structure. You can use egresados_atr[names(egresados)] as he points out if the data is not sorted in the same order or have an unequal number of elements.