How to count the number of components every time a graph is updated in R

Viewed 213

I have the following data:

data <- data.frame(name = c("A", "A", "A", "B", "B", "C", "D", "D", "D", "D", "E", "B", "C", "C"),
                 surname = c("aa", "bb", "cc", "dd", "hh", "ee", "ii", "aa", "qq", "ff", "gg", "ff", "gg", "cc"))

This data produces a connected graph:

plot(graph_from_data_frame(data, directed = F))

which obviously has 1 component.

I would like to count the number of components this data produces every time we add a row in the graph. For example, the initial graph will have 1 component, since the vertices A and aa in the first row of the data are connected. The next graph will have again 1 component, since we add the second row and because of the A value in the name column. When we include the fourth row (B, dd), the graph will have 2 components.

I use the following piece of code to get the number of components each time the data is updated:

for (i in 1:dim(data)[1]) {
data$number_of_components[i] <- components(graph_from_data_frame(data[1:i,], directed = F))$no}

Is there a smarter/more sophisticated way to get this? Thanks.

2 Answers

You can take a look at sapply().

dt$number_of_components <- sapply(seq_len(nrow(dt)), function(x) {
  g <- graph_from_data_frame(dt[seq_len(x),], directed = FALSE)
  components(g)$no
})

dt

#    name surname number_of_components
# 1     A      aa                    1
# 2     A      bb                    1
# 3     A      cc                    1
# 4     B      dd                    2
# 5     B      hh                    2
# 6     C      ee                    3
# 7     D      ii                    4
# 8     D      aa                    3
# 9     D      qq                    3
# 10    D      ff                    3
# 11    E      gg                    4
# 12    B      ff                    3
# 13    C      gg                    2
# 14    C      cc                    1

You can try decompose like below

transform(
    data,
    num_components = sapply(
        seq_along(name),
        function(k) length(decompose(graph_from_data_frame(head(data, k), directed = FALSE)))
    )
)

or

transform(
    data,
    num_components = lengths(
        sapply(
            seq_along(name),
            function(k) decompose(graph_from_data_frame(head(data, k), directed = FALSE))
        )
    )
)

which gives

   name surname num_components
1     A      aa              1
2     A      bb              1
3     A      cc              1
4     B      dd              2
5     B      hh              2
6     C      ee              3
7     D      ii              4
8     D      aa              3
9     D      qq              3
10    D      ff              3
11    E      gg              4
12    B      ff              3
13    C      gg              2
14    C      cc              1
Related