问题
A - I have a list containing igraph
graph objects:
goodgg
[[1]]
IGRAPH UN-- 3 3 --
+ attr: name (v/c), color (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 89315--89316 89315--89928 89316--89928
[[2]]
IGRAPH UN-- 3 2 --
+ attr: name (v/c), color (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 106277--106278 106278--106279
I can combine these into a single object using [union][1]
:
combine = graph.union(goodgg[[1]], goodgg[[2]], byname=T)
combine
IGRAPH UN-- 6 5 --
+ attr: color_1 (v/c), color_2 (v/c), name (v/c)
+ edges (vertex names):
From this, I can extract particular attributes e.g. a color
, which lines up with the order of the original objects (1 - 2):
as.list(get.vertex.attribute(combine))
$color_1
[1] "red" "red" "orange" NA NA NA
$color_2
[1] NA NA NA "red" "red" "red"
$name
[1] "89315" "89316" "89928" "106277" "106278" "106279"
How can I extract the non NA
values in $color_1
and $color_2
and merge them into a new list when I have an arbitrary number of color_n
entries? (E.g. I have n entries)?
To get:
[1] "red" "red" "orange" "red" "red" "red"
What I tried (which does not work for n
color_
variables:
In this simple case I can do what this answer did here:
V(combine)$color <- ifelse(is.na(get.vertex.attribute(combine)$color_1), get.vertex.attribute(combine)$color_2,get.vertex.attribute(combine)$color_1)
get.vertex.attribute(combine)$color
[1] "red" "red" "orange" "red" "red" "red"
However, in reality my list could have n
elements. How can I adjust this to account for n
elements?
I considered using multiple nested IFELSE statements such as here and here a la:
V(combine)$color <- ifelse(is.na(get.vertex.attribute(combine)$color_1), ifelse(is.na(get.vertex.attribute(combine)$color_2), ifelse(get.vertex.attribute(combine)$color_3)......))
This does not work for unknown n
attributes and does not solve the issue of having an unknown number n
of attributes to work with.
Many thanks for your help.
回答1:
You can use Reduce
to "cumulatively" apply a function over a vector:
set.seed(125)
color_choices <- c("red", "orange", NA)
color_samples <- replicate(
4,
sample(color_choices, 5, replace = TRUE),
simplify = FALSE
)
color_samples
# [[1]]
# [1] NA "red" "red" "orange" NA
#
# [[2]]
# [1] NA "orange" "red" "orange" "orange"
#
# [[3]]
# [1] "red" NA "orange" "red" "orange"
#
# [[4]]
# [1] "orange" "orange" NA NA NA
Reduce(
f = function(a, b) ifelse(is.na(a), b, a),
x = color_samples
)
# [1] [1] "red" "red" "red" "orange" "orange"
In this case, Reduce
applied the function to the first and second elements, then to that result and the third element, then to that result and the fourth element. If the list were longer, it would've kept going on that way.
Edit for your specific situation: save the list of attributes, find which have names like color_n
, and then use the Reduce
solution on those.
combine_attributes <- as.list(get.vertex.attribute(combine))
Because I don't have your data, let's just say combine_attributes
looks like the color_samples
created above with an extra element:
combine_attributes
# $color_1
# [1] NA "red" "red" "orange" NA
#
# $color_2
# [1] NA "orange" "red" "orange" "orange"
#
# $color_3
# [1] "red" NA "orange" "red" "orange"
#
# $color_4
# [1] "orange" "orange" NA NA NA
#
# $name
# [1] "89315" "89316" "89928" "106277" "106278"
color_attributes <- grep(
"^color_\\d+$",
names(combine_attributes),
value = TRUE
)
color_attributes
# [1] "color_1" "color_2" "color_3" "color_4"
Reduce(
f = function(a, b) ifelse(is.na(a), b, a),
x = combine_attributes[color_attributes]
)
# [1] "red" "red" "red" "orange" "orange"
来源:https://stackoverflow.com/questions/47637321/combine-non-na-values-for-n-lists-r