I am working on julia with the Metagraphs.jl library.
In order to conduct an optimization problem, I would like to get the set/list of edges in the graph that point to a special set of vertices having 2 particular properties in common.
My first guess was to first get the set/list of vertices. But I am facing a first issue which is that the filter_vertices function doesn't seem to accept to apply a filter on more than one property.
Here is below an example of what I would like to do:
g = DiGraph(5)
mg = MetaDiGraph(g, 1.0)
add_vertex!(mg)
add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)
set_props!(mg,3,Dict(:prop1=>1,:prop2=>2))
set_props!(mg,1,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,2,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,4,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,5,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,6,Dict(:prop1=>0,:prop2=>0))
col=collect(filter_vertices(mg,:prop1,1,:prop2,2))
And I want col to find vertex 3 and no others.
But the filter_vertices would only admit one property at a time and then it makes it more costly to do a loop with 2 filters and then try to compare in order to sort a list with the vertices that have both properties.
Considering the size of my graph I would like to avoid defining this set with multiple and costly loops. Would any one of you have an idea of how to solve this issue in an easy and soft way?
I ended up making this to answer my own question:
fil3=Array{Int64,1}()
fil1=filter_vertices(mg,:prop1,1)
for f in fil1
if get_prop(mg,f,:prop2)==2
push!(fil3,f)
end
end
println(fil3)
But tell me if you get anything more interesting
Thanks for your help!
Please provide a minimal working example in a way we can simply copy and paste, and start right away. Please also indicate where the problem occurs in the code. Below is an example for your scenario:
Pkg.add("MetaGraphs")
using LightGraphs, MetaGraphs
g = DiGraph(5)
mg = MetaDiGraph(g, 1.0)
add_vertex!(mg)
add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)
set_props!(mg,3,Dict(:prop1=>1,:prop2=>2))
set_props!(mg,1,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,2,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,4,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,5,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,6,Dict(:prop1=>0,:prop2=>0))
function my_vertex_filter(g::AbstractMetaGraph, v::Integer, prop1, prop2)
return has_prop(g, v, :prop1) && get_prop(g, v, :prop1) == prop1 &&
has_prop(g, v, :prop2) && get_prop(g, v, :prop2) == prop2
end
prop1 = 1
prop2 = 2
col = collect(filter_vertices(mg, (g,v)->my_vertex_filter(g,v,prop1,prop2)))
# returns Int[3]
Please check ?filter_vertices --- it gives you a hint on what/how to write to define your custom filter.
EDIT. For filtering the edges, you can have a look at ?filter_edges to see what you need to achieve the edge filtering. Append the below code excerpt to the solution above to get your results:
function my_edge_filter(g, e, prop1, prop2)
v = dst(e) # get the edge's destination vertex
return my_vertex_filter(g, v, prop1, prop2)
end
myedges = collect(filter_edges(mg, (g,e)->my_edge_filter(g,e,prop1,prop2)))
# returns [Edge 1 => 3]
I found this solution:
function filter_function1(g,prop1,prop2)
fil1=filter_vertices(g,:prop1,prop1)
fil2=filter_vertices(g,:prop2,prop2)
filter=intersect(fil1,fil2)
return filter
end
This seems to work and is quite easy to implement.
Just I don't know if the filter_vertices function is taking a lot of computational power.
Otherwise a simple loop like this seems to also work:
function filter_function2(g,prop1,prop2)
filter=Set{Int64}()
fil1=filter_vertices(g,:prop1,prop1)
for f in fil1
if get_prop(g,f,:prop2)==prop2
push!(filter,f)
end
end
return filter
end
I am open to any other answers if you have some more elegant ones.
Related
Suppose we have given dataframe in R. By 0--7, it means it is taking integer values from 0-7 i.e. 0,1,2,3,4,5,6,7.
I am interested in making a function such that
If a[1,1]>alpha, it goes and checks its children i.e. 0--7 consists of a[1,2] and a[2,2].
So,
{a[2,1]>alpha
{a[4,1]>alpha
{a[5,1]>alpha
ps=list.append(0)
else ps=list.append(1)
}}}
Here, alpha is a a threshold. The ps is appended from values of 0 to 15 based on this criteria.
My code is
{for (i in 1:2)
{ if (a[j,i]>alpha)
{if (i%%2==1}
{j=j*2
if (a[j,i]>alpha
###here i want to go recursively i think and where and how should i add append values to the list
if a[j,i+1]>alpha}
if{i%%2==0}
{}
}}
I am stuck and confused at the same time. Any help or advices would be greatly appreciated.
Thanks
I am unable to define empty IndexedTables, e.g.
using IndexedTables, IndexedTables.Table
t = Table(Columns(a=Int64[],b=String[]),Int64[])
t[1,"a"] = 1
t[1,"b"] = 2
t[1,"c"] = t[1,"a"] + t[1,"b"]
BoundsError: attempt to access 0-element Array{Int64,1} at index [0]
I am aware that creating the IndexedTable with already the data is more efficient that creating an empty one and then insert values, but sometimes you are obliged to go on this way.
Is this a bug ? If so, is there any workaround possible ?
(I already posted this thread on the Julia forum, but so far I had no replies there)
This is probably a bug in IndexedTables.
Inserting into an IndexedTable requires reindexing to access the data. Reindexing is done with flush!.
But flush!(t) fails in the example in the question with the empty t.
Fixing flush! which calls _merge! can be done by:
julia> function IndexedTables._merge!(dst::IndexedTable, src::IndexedTable, f)
if length(dst.index)==0 || isless(dst.index[end], src.index[1])
append!(dst.index, src.index)
append!(dst.data, src.data)
else
# merge to a new copy
new = _merge(dst, src, f)
ln = length(new)
# resize and copy data into dst
resize!(dst.index, ln)
copy!(dst.index, new.index)
resize!(dst.data, ln)
copy!(dst.data, new.data)
end
return dst
end
julia> t[1,"c"] = t[1,"a"] + t[1,"b"]
3
The change is the addition of the length(...) check in the first if.
Of course, a pull request / issue should be opened with IndexedTables.jl. Antonello, will you do this? (or shall I)
I am plotting a sunburst donut and I cannot figure out why the total is incorrect.
library(sunburstR)
reports <- data.frame(
sequence = c("SVP-VP-Dir-end","SVP-VP-Dir-end","SVP-VP-Dir-end","SVP-VP-Dir-end","SVP-No VP-Dir-end","SVP-No VP-Dir-end","SVP-No VP-Dir-end"),
freq = as.numeric(c("167","60","51","32","5","1","1")))
sunburst(reports, count = TRUE)
It is supposed to be 100% 317 of 317 . Anyone know how to fix this? There is not much documentation on this great package.
Also, I would like it to have a default value in the center of donut.
If there is another way to create an interactive donut using R, please let me know.
Thanks you in advance.
It looks like the default function generating the message in the center of the donut rounds the total value to the nearest ten.
But you can customize this function using the explanation argument of sunburst. Oddly, the customized function (in javascript) must be provided as a string.
Try the following function:
custom.message = "function (d) {
root = d;
while (root.parent) {
root = root.parent
}
p = (100*d.value/root.value).toPrecision(3);
msg = p+' %<br/>'+d.value+' of '+root.value;
return msg;
}"
Now:
sunburst(reports, explanation = custom.message )
will generate the donut displaying exact total values. The count argument is no longer needed, as it is used by the default explanation function.
The value returned by custom.message is html code. As you can see, I've just inserted a line break (<br/>). You can modify the msg return value to further customize the look and feel.
I am struggling with a loop in R where I have to use dynamic variable names (which I am told is a bad idea from the other posts about dynamic variable names, but I am pretty sure that I need to based on my file structure). Each folder for which the loop enters, there is a different number of files.
The dynamic variable names contain matrices and I need to look in each row/column of the matrix and output a new matrix.
Streamlined example:
var 1 is a matrix(0,40,40)
var 2 is a matrix(0,45,45)
var 3 is a matrix(0,40,40)
For (f in 1:(length of var3s)) # the number of files in the folder, in each folder:
For (g in 1: ncol(var1)) {
For (h in 1: nrow(var1)) {
if (var 1[g,h]>4 & var 2[g,h]<1)
{ var3[f] [g,h]<-1} # <- you cannot do this, but this is ultimately what I want
}
}
I want to take the f-th variable matrix from variable 3's list and assign a value to the location at [g,h]
I've done this before with real variable names, but I am struggling with adding the dynamic element. This is what it looks like and the errors I'm getting.
for (f in 1:(length(LD139_040))){
assign(paste0("LD139_040s",f),
matrix(0,nrow(eval(parse(text=paste0("B139_040",f)))),
ncol(eval(parse(text=paste0("B139_040",f)))))) # this effectively creates my new matrix (var3 above) the size I need based on the files above
for (g in 1:(ncol(eval(parse(text=paste0("B139_040",f)))))){
for (h in 1:(nrow(eval(parse(text=paste0("B139_040",f)))))){
if (S139_040[g,h]>10 &
(assign(paste0("LD139_040",f), as.matrix(raster(LD139_040[f]))))[g,h]>.295 &
(assign(paste0("LD139_040",f), as.matrix(raster(LD139_040[f]))))[g,h]<.33 &
(assign(paste0("B139_040",f), as.matrix(raster(Blue139_040[f]))))[g,h]<180)
# this section also works and will give me a t/f at each location [g,h]
# if true, assign the value 1 to the new matrix LD139_040 at f
{assign(paste0("LD139_040s", f)[g,h], 1)}
}
}
}
I have tried a variety of combinations of eval and assign to organize the last statement, and I get errors such as 'invalid first assignment', incorrect number of dimensions, and target of assignment expands to non-language object.
Thanks for your help!
R version 3.1.1 "Sock it to Me" with library(raster)
This did not require dynamic variable names. At each iteration within the loop the all of the names will change at the same time.
For example, this is how I answered the section in code block 2:
for (f in 1:(length(LD139_040))){
currenttile<-LD139_040[f]
Blue<-B139_040[f]
newmatrix<- matrix(0,nrow(Blue),ncol(Blue))
for (g in 1:(ncol(B139_040[f]))){
for (h in 1:(nrow(B139_040[f]{
if (S139_040[g,h]>10 & currenttile[g,h]>.295 & currenttile[g,h]<.33 & Blue [g,h]<180)
{newmatrix[g,h]<-1}
}
}
}
Put even more simply, since I learned that as long as the matrices are the same dimensions, you do not have to loop through each location:
for (f in 1:(length(LD139_040))){
currenttile<-LD139_040[f]
Blue<-B139_040[f]
newmatrix<- matrix(0,nrow(Blue),ncol(Blue))
currenttile[currenttile >.295 & currenttile <.33]<- 1
Blue[Blue<180]<- 1
newmatrix[Blue==1 & currenttile==1]<- 1
}
So thanks to everyone who tried to decipher this, it was a confusing problem for me to it took a while to figure out how to best approach it, (and obviously how to explain it). I hope this helps someone!
I am using the Graph package in R for maxclique analysis of 5461 items.
The final output item which I get is very long, so I am getting the following warning:
reached getOption("max.print") -- omitted 475569 rows
Can somebody please provide me the pointers with how to increase the limit
for max.print.
Use the options command, e.g. options(max.print=1000000).
See ?options:
‘max.print’: integer, defaulting to ‘99999’. ‘print’ or ‘show’
methods can make use of this option, to limit the amount of
information that is printed, to something in the order of
(and typically slightly less than) ‘max.print’ _entries_.
See ?options:
options(max.print=999999)
You can use the options command to change the max.print value for the value limit you want to reach. For example:
options(max.print = 1000000)
There you can change the value of the max.print in R.
set the function options(max.print=10000) in top of your program. since you want intialize this before it works. It is working for me.
I fixed it just now. But it looks busty. Anyone make it simple please?
def list_by_tag_post(request):
# get POST
all_tag = request.POST.getlist('tag_list')
arr_query = list(all_tag)
for index in range(len(all_tag)):
tag_result = Tag.objects.get(id=all_tag[index])
all_english_text = tag_result.notes.all().values('english_text', 'id')
arr_query[index] = all_english_text
for index in range(len(arr_query)):
all_english_text = all_english_text | arr_query[index]
# Remove replicated items
all_english_text = all_english_text.order_by('id').distinct()
# render
context = {'all_english_text': all_english_text, 'all_tag': all_tag}
return render(request, 'list_by_tag.html', context)