Saad
Saad

Reputation: 391

S4 class list to data frame

I an new to S4 classes and looked around for a solution but failed :( I have a S4 class list, not sure if it is nested list but i want to change it to data frame. My list looks like this named z

head(z)
[[1]]
An object of class "AgNode"
Slot "center":
x: 1515, y: 2258

Slot "name":
[1] "hsa:4052"

Slot "txtLabel":
An object of class "AgTextLabel"
Slot "labelText":
[1] "hsa:4052"

Slot "labelLoc":
x: 0, y: 0

Slot "labelJust":
[1] "n"

Slot "labelWidth":
[1] 50

[[2]]
An object of class "AgNode"
Slot "center":
x: 1443, y: 2567

Slot "name":
[1] "hsa:1311"

Slot "txtLabel":
An object of class "AgTextLabel"

and so on, I want to extract the X and Y values from the center slot and name from the name slot. And put the three in a data frame. How can i do this ?

see<-do.call(cbind, lapply(z, stack))

i tried this but it gives an error

Error in as.list.default(x) : 
no method for coercing this S4 class to a vector

can anybody help me ?

Upvotes: 3

Views: 2985

Answers (1)

hrbrmstr
hrbrmstr

Reputation: 78792

If you want a "one-liner":

purrr::map_df(x, ~as.list(set_names(getPoints(getNodeCenter(.)), c("x", "y"))))`

but I like to spell these out if there's no performance hit since ultimately we're programming for humans:

library(Rgraphviz)
library(purrr)

V <- letters[1:10]
M <- 1
g1 <- randomGraph(V, M, .2)
z <- agopen(g1,name="foo")
x <- AgNode(z)

map(x, getNodeCenter) %>%
  map(getPoints) %>%
  map(set_names, c("x", "y")) %>%
  map_df(as.list)
## # A tibble: 10 × 2
##        x     y
##    <int> <int>
## 1     73   348
## 2     73   243
## 3    145   348
## 4    217   348
## 5    289   348
## 6     27   137
## 7     82    32
## 8    361   348
## 9    433   348
## 10   505   348

That's also:

library(magrittr)

lapply(x, getNodeCenter) %>%
  lapply(getPoints) %>%
  lapply(set_names, c("x", "y")) %>%
  lapply(as.list) %>% 
  do.call(rbind.data.frame, .)

if you don't want to use purrr but are willing to use piping or:

do.call(rbind.data.frame, lapply(x, function(y) {
  as.list(setNames(getPoints(getNodeCenter(y)), c("x", "y")))
}))

if you don't like piping, or:

do.call(rbind.data.frame, lapply(x, function(y) {
   tmp <- getNodeCenter(y)
   tmp <- getPoints(tmp)
   tmp <- setNames(tmp, c("x", "y"))
   as.list(tmp)
}))

if you want it to be readable and not use purrr or piping.

Upvotes: 4

Related Questions