0

In the nested list below, I need to set row names to resource and the row names should be taken from bodyPart. I want this to be applied to all objects (e.g., obj1, obj2)

obj1 <- list(resource = list(bodyPart = c("leg", "arm", "knee"),side = c("LEFT", "RIGHT", "LEFT"), device = c("LLI", "LSM", "GHT")), cat = list(lab = c("aa", "bb", "cc")))
obj2 <- list(resource = list(bodyPart = c("leg", "arm", "knee"), side = c("LEFT", "LEFT", "LEFT"), device = c("GOM", "LSM", "YYY")))

x <- list(foo = c(fer = "wdb", obj1), bar = obj2)

I would like the output to look like this at resource level, for instance for obj2.

bodyPart side device
leg leg LEFT GOM
arm arm LEFT LSM
knee knee LEFT YYY

I appreciate your edvice.

Rara
  • 105
  • 9
  • Your code was a parsing error, I added the missing parens. Beyond that ... you talk about row-names as if you have frames, but these are only nested lists. Do you need to know also how to convert from a list to a frame? ...pause... Actually, these are more-deeply nested lists, where `$resource` is an added level. Where is the `$resource` layer supposed to go in this example? – r2evans Jun 29 '23 at 15:43
  • @r2evans Thanks for the correction. I updated my data2frame. This is how my real data looks like but I am not able to show that the type of resource level should be `list[3*3] (s3:dataframe)`. I want the data frame to exactly look like how it is now but with the row names added. – Rara Jun 29 '23 at 21:56

2 Answers2

1

Alternatively we could use

obj2$resource %>% as.data.frame() %>% mutate(bodyPart2=bodyPart) %>% 
column_to_rownames(var = 'bodyPart2')

# output

     bodyPart side device
leg       leg LEFT    GOM
arm       arm LEFT    LSM
knee     knee LEFT    YYY

jkatam
  • 2,691
  • 1
  • 4
  • 12
0

Edited to make it a double-lapply:

lapply(x, function(y) {
  lapply(y, function(z) {
    if ("bodyPart" %in% names(z)) {
      `rownames<-`(as.data.frame(z), z[["bodyPart"]])
    } else z
  )
)
# $foo
# $foo$fer
# [1] "wdb"
# $foo$resource
#      bodyPart  side device
# leg       leg  LEFT    LLI
# arm       arm RIGHT    LSM
# knee     knee  LEFT    GHT
# $foo$cat
# $foo$cat$lab
# [1] "aa" "bb" "cc"
# $bar
# $bar$resource
#      bodyPart side device
# leg       leg LEFT    GOM
# arm       arm LEFT    LSM
# knee     knee LEFT    YYY
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • Wonderful! Just as a practice, I tried to rewrite the code using rownames() function but it does not work. Can you correct me please? `rowname <- lapply(x, function(z) (as.data.frame(z$variables)) rownames <- z$variables[[1]])` – Rara Jun 29 '23 at 21:30
  • The only problem with this code is it removes other lists and values. To show you what I mean, I updated my dataframe. The code removes `fer` and `cat` from the output. Could you please advise me on this too? – Rara Jun 29 '23 at 21:59
  • See my edit @Rara – r2evans Jun 30 '23 at 11:48
  • Thanks! Do you mind explaining the logic behind using two lapplys? What does y represent here? – Rara Jun 30 '23 at 12:21
  • 1
    They just delve into the first and second layer (respectively) of the list; the `if ("bodyPart" %in%..)` part is to ensure we don't try to convert to a frame where we don't see the `bodyPart` column, so we preserve (unchanged) `fer` and `cat`. – r2evans Jun 30 '23 at 12:25
  • Could you please help me with another issue? I realized, strangely, in my data the column `bodyPart` exists also in `cat` but that is irrelevant to what I am doing. How can I specify in the code that only consider `bodyPart` in `resource`? – Rara Jul 07 '23 at 09:39
  • 1
    `if (all(c("body part","side","device") %in% names(z))) ...`? Look at the *intent* of the code -- to ensure that enough guaranteed properties of the frame are present -- and adapt the code to the intent. – r2evans Jul 07 '23 at 10:57