1

I am quite new to RDFLIB and I am trying to learn how to use Delete/Insert statement to continually update data property values of individuals in my ontology from a CSV file. I am using pandas dataframe to do this but I am now stuck.

I am able to do this successfully if I am to use values directly such as 23, 34.6, 13330, etc. but my challenge is that this does not work if I read data from CSV and store it a variable say 'x'. Here is the section of my codes that works fine:

g.update( """ DELETE { ?Product myontology:LifecycleData ?lifecycle } INSERT { ?Product myontology:LifecycleData 243 } WHERE { ?Product myontology:LifecycleData ?lifecycle . } """)

Now, if I assign the value 243 to x, that is x=243 and replace 243 with x in the code above, I get errors. Can somebody help me on how to manipulate this? I can provide more information if needed but I am trying to keep it short. Thank you in advance.

  • this is just Python string interpolation or not? And indeed you can'T pass a Pandas dataframe to the query command. You have to iterate all possible values of `x` and just interpolate the string – UninformedUser Sep 06 '21 at 12:31
  • 1
    @UninformedUser thank you for your comment. The variable I am using is obtained this way `x=df.tail(1)['Usecycle left'].values[0]` . so it is a single value that should have worked. How do I do the string interpolation? Do you want to share more info on that or point me to an example? – JustWantToLearn Sep 06 '21 at 12:37
  • By the way, I do not understand what the result of your task would be. So far you are deleting all triples that match `?Product myontology:LifecycleData ?lifecycle` - ok. But then you add to each product a set of values, and each product gets the same values? – UninformedUser Sep 06 '21 at 12:42
  • Python string interpolation is explained even here on StackOverflow: https://stackoverflow.com/questions/10112614/how-do-i-create-a-multiline-python-string-with-inline-variables – UninformedUser Sep 06 '21 at 12:43
  • @UninformedUser thank you once again. Since your last comment, I have been trying out different solutions but failing. I am suspecting conflicting special characters like { and ? are affecting my result and giving me errors. – JustWantToLearn Sep 06 '21 at 15:02
  • This is how I modified my code but I am getting error: `g.update( """\ DELETE { ?Product myontology:LifecycleData ?lifecycle } INSERT { ?Product myontology:LifecycleData {} } WHERE { ?Product myontology:LifecycleData ?lifecycle . }\ """.format(x))` The error message is in the next comment. – JustWantToLearn Sep 06 '21 at 15:27
  • This is the error message. KeyError Traceback (most recent call last) in ----> 1 g.update("""\ 2 DELETE {?Product myontology:LifecycleData ?lifecycle } 3 INSERT { ?Product myontology:LifecycleData 3454} 4 WHERE 5 { ?Product myontology:LifecycleData ?lifecycle . FILTER(?Product= myontology:Pump2)}; KeyError: '?Product myontology' – JustWantToLearn Sep 06 '21 at 15:28
  • in Python multiline strings you can't use the fancy Python 3 string interpolation via curly brackets without escaping the curly brackets of the SPARQL query itself - this is quite obvious, the Pythin interpreter treat everything between `{}` as a variable - you have to escape it with `\` char – UninformedUser Sep 06 '21 at 17:24

1 Answers1

1

I would separate your string query building from query submission and test the query (visually) and ensure that it's correct like this:

q = """
    DELETE {
        ?Product myontology:LifecycleData ?lifecycle 
    }
    INSERT {
        ?Product myontology:LifecycleData xxx 
    }
    WHERE {
        ?Product myontology:LifecycleData ?lifecycle  
    }
    """.replace("xxx", str(df.tail(1)['Usecycle left'].values[0]))

# I like to use replace() rather than string templating
# so I don't have to escape characters like { in the query

print(q)  # does it look like you expect it to at this point?

# then...
g.update(
    q, 
    initNs={
        "myontology": Namespace("http://example.com/myontology#")
    }
)
Nicholas Car
  • 1,164
  • 4
  • 7
  • thank you so much. This should have work but there is a conflict with type and therefore throwing a type error. `TypeError: replace() argument 2 must be str, not numpy.int64`. Anyway out? – JustWantToLearn Sep 07 '21 at 12:07
  • the error message should already indicate the way ... you have to convert the int to a string, e.g. `str(df.tail(1)['Usecycle left'].values[0])` is the way to go - and by the way, you should learn the Python basics as this is pure string work stuff – UninformedUser Sep 07 '21 at 12:50
  • @UninformedUser yeah I thought of that but was afraid that since integer is needed to update the data properties. I thought it was not going to work. However, I tried it and it worked. I actually queried the ontology in GRAPHDB and it worked like magic with the correct data type and plotted charts using Google charts. I must say I am grateful. What I am doing is to delete the existing triple that matched the condition given using `FILTER` function and then insert new triple with the new data. – JustWantToLearn Sep 07 '21 at 15:05
  • @Nicholas, your answer now works after converting to string like this: `str(df.tail(1)['Usecycle left'].values[0])` . Should I accept your answer like that or you want to correct it before before accepting it? – JustWantToLearn Sep 07 '21 at 15:11
  • RDFlib `query` and `update` methods take a keyword arg `initBindings=` but I have found that to be broken. I tend to use `string.Template` nowadays to insert values into a query template, but you have to make sure that whatever gets substituted into the query is valid SPARQL syntactically. – Ora Lassila Sep 07 '21 at 18:03
  • @JustWantToLearn thanks for replying about the str(). I've altered the answer to reflect this so you can accept! – Nicholas Car Sep 08 '21 at 00:40
  • @OraLassila yes, that's true (that there is an `initBindings`). I tend not to use it as I find it helpful to assemble the query before lodging it, as per my example, so I can print it out etc. in development! String templates, f-strings: many ways to get vars into the query string! – Nicholas Car Sep 08 '21 at 00:42
  • @NicholasCar Thank you for the help. – JustWantToLearn Sep 09 '21 at 22:44
  • @OraLassila do you have any example one learn how to use `string.Template`. Will be good to learn that too. – JustWantToLearn Sep 09 '21 at 22:46
  • Something like `graph.query(string.Template(querystring).substitute(bindings))` where _querystring_ is something like `"SELECT * { $foo ?p ?o }"` (with _$foo_ being a variable to be substituted) and _bindings_ a `dict` with (in this case) a key `"foo"` and a value you want substituted. Note that this is a string substitution, so you need to make sure the substitutions will result in valid SPARQL syntax. – Ora Lassila Sep 10 '21 at 15:32
  • @OraLassila Thank you for this and I will give it a go and see. – JustWantToLearn Sep 11 '21 at 12:24