SUTime custom date parsing - stanford-nlp

Need to parse a sentence like "Bob was born on Jan fifteen nineteen seventy nine." and extract the date. How do I create a new rule to handle the date expression?
If I use "Bob was born on Jan fifteenth nineteen seventy nine." the parser extracts the correct date 01/15/1979. Simply changing "fifteenth" to "fifteen" leads to incorrect parsing.
val input = "Bob was born on Jan fifteenth nineteen seventy nine."
val document = new CoreDocument(input)
val props = new Properties()
val annotators_ner = "tokenize,ssplit,pos,lemma,ner"
props.setProperty("annotators", annotators_ner)
val pipeline = new StanfordCoreNLP(props)
pipeline.annotate(document)
val writer = new StringWriter
pipeline.jsonPrint(document.annotation(), writer);
val json = writer.toString()
println(json)
The json excerpt below shows correct entity mentions.
"entitymentions": [
{
"docTokenBegin": 0,
"docTokenEnd": 1,
"tokenBegin": 0,
"tokenEnd": 1,
"text": "Bob",
"characterOffsetBegin": 0,
"characterOffsetEnd": 3,
"ner": "PERSON"
},
{
"docTokenBegin": 4,
"docTokenEnd": 9,
"tokenBegin": 4,
"tokenEnd": 9,
"text": "Jan fifteenth nineteen seventy nine",
"characterOffsetBegin": 16,
"characterOffsetEnd": 51,
"ner": "DATE",
"normalizedNER": "1979-01-15",
"timex": {
"tid": "t1",
"type": "DATE",
"value": "1979-01-15"
}
}
]
Changing the input as follows.
val input = "Bob was born on Jan fifteen nineteen seventy nine."
Leads to the following output for entity mentions.
"entitymentions": [
{
"docTokenBegin": 0,
"docTokenEnd": 1,
"tokenBegin": 0,
"tokenEnd": 1,
"text": "Bob",
"characterOffsetBegin": 0,
"characterOffsetEnd": 3,
"ner": "PERSON"
},
{
"docTokenBegin": 4,
"docTokenEnd": 7,
"tokenBegin": 4,
"tokenEnd": 7,
"text": "Jan fifteen nineteen",
"characterOffsetBegin": 16,
"characterOffsetEnd": 36,
"ner": "DATE",
"normalizedNER": "1519-01",
"timex": {
"tid": "t1",
"type": "DATE",
"value": "1519-01"
}
},
{
"docTokenBegin": 7,
"docTokenEnd": 9,
"tokenBegin": 7,
"tokenEnd": 9,
"text": "seventy nine",
"characterOffsetBegin": 37,
"characterOffsetEnd": 49,
"ner": "NUMBER",
"normalizedNER": "79.0"
}
]

This is complicated because I think the rules are recognizing "Jan fifteen nineteen" as January 1519. One thing you could try is adding some post-processing rules if you find a common pattern such as "DATE" followed by "NUMBER" is actually a written out "DATE". But you could imagine scenarios such as "In Jan Fifteen Nineteen Seventy Nine people visited".
There is a full write up about how to add TokensRegex rules to the ner pipeline here: https://stanfordnlp.github.io/CoreNLP/ner.html
and info on writing tokensregex rules here: https://stanfordnlp.github.io/CoreNLP/tokensregex.html

Related

Retrieving data from REST API

I am trying to implement my first project in Laravel that will contain APIs, more specifically the Sportmonks API. What is the best way to get the data and display it in my view?
I have managed to display some of the data, but I do not know the correct way to display the data from the "standings", as well as from the tables that it has in it (overall, home, away, total)
API returns
{
"data": [{
"id": 77447501,
"name": "1st Phase",
"league_id": 501,
"season_id": 17141,
"round_id": 195000,
"round_name": 33,
"type": "Group Stage",
"stage_id": 77447501,
"stage_name": "1st Phase",
"resource": "stage",
"standings": {
"data": [{
"position": 1,
"team_id": 62,
"team_name": "Rangers",
"round_id": 195000,
"round_name": 33,
"group_id": null,
"group_name": null,
"overall": {
"games_played": 33,
"won": 28,
"draw": 5,
"lost": 0,
"goals_scored": 78,
"goals_against": 10,
"points": 89
},
"home": {
"games_played": 16,
"won": 16,
"draw": 0,
"lost": 0,
"goals_scored": 47,
"goals_against": 2,
"points": 48
},
"away": {
"games_played": 17,
"won": 12,
"draw": 5,
"lost": 0,
"goals_scored": 31,
"goals_against": 8,
"points": 41
},
"total": {
"goal_difference": "68",
"points": 89
},
"result": "Championship Round",
"points": 89,
"recent_form": "WWWWD",
"status": null
}],....
}
}]
}
Controller
public function index() {
$response = Http::get('apiurl');
$response->json();
$result = json_decode($response, true);
$matches = $result['data'];
return view('/api', compact('matches'));
}
Instead of returning json you can return object
$response = Http::get('apiurl');
$result=$response->object();
$matches=$result->data;
return view('/api', compact('matches'));
then in your view
#foreach($matches as $match)
#foeach($match->standings->data as $standing)
{{$standing->team_name??null}}
#endforeach
#endforeach

How to merge two collections with a specific condition in laravel?

I have Two collections competences and coCompetences those collections look like :
competence :
...
{
"id": 6,
"category_id": 17,
"user_id": 1,
"objective_level": 4,
"current_level": 4,
"target_date": "2021-11-28",
"obtained_date": "2022-10-14",
"comment": "",
"created_at": "2020-01-08 10:06:28",
"updated_at": "2020-01-08 10:06:28",
"name": null,
"competenceName": "Hierarchy Building & BOM (Bill of Material)",
"category": {
"id": 17,
"competence": "Hierarchy Building & BOM (Bill of Material)",
"created_at": "2020-01-08 09:53:55",
"updated_at": "2020-01-08 09:53:55",
"wheel_id": 10
}
},
{
...
coCompetences :
{
"category": {
"id": 12,
"competence": "Criticality Analysis",
"created_at": "2020-01-08 09:53:55",
"updated_at": "2020-01-08 09:53:55",
"wheel_id": 10
},
"user_id": 1,
"competenceName": "Criticality Analysis",
"category_id": 12,
"objective_level": 0,
"current_level": 0,
"target_date": "2020-01-14",
"obtained_date": "2020-01-14",
"comment": ""
},
I would like to push only coCompetences elements into competences where coCompetences.category_id are not exist in competences.category_id
in another way : add all coCompetences elements to competences except those where coCompetences.category_id already exists in coCompetences.
I don't want to write code instead of you, algorithm will be enough, I hope.
simplest way
Take array Ids from first array, for example by pluck()
Filter second and return items that don't exist in first
push filtered data to first

Laravel collection sum of columns group by month

I'm working on Laravel project where I need to fetch some data, sum the columns and group the results in M-y (Jan-19) format to show in a monthly bar graph chart.
I was able to successfully get the data sum'ed and grouped but the problem is, for the months without any records, I still want to show up in the graph with a total equals to 0.
This is my current approach:
$data = $this->user->income()
->whereBetween('game_date', ['2019-01-01', '2019-04-30'])
->selectRaw('sum(total_score) as score,
sum(total_stars) as stars,
MONTH(game_date) as month,
DATE_FORMAT(game_date,"%b") as month_name
')
->groupBy('month', 'month_name')
->get();
This gives me the following result (missing months without any records):
[
{
"score": "707",
"stars": "64",
"month": 1,
"month_name": "Jan"
},
{
"score": "200",
"stars": "29",
"month": 3,
"month_name": "Mar"
}
]
And the expected result is including missing months to making visually clear chart as:
[
{
"score": "707",
"stars": "64",
"month": 1,
"month_name": "Jan"
},
{
"score": "0",
"stars": "0",
"month": 2,
"month_name": "Feb"
},
{
"score": "200",
"stars": "29",
"month": 3,
"month_name": "Mar"
},
]
Please note that the ->whereBetween('game_date', []) will aways have dates from start of month and end of month (covering full monthly records).
you have to use COALESCE() function. It's because at the month of Feb you get null at sum(total_score) as score instead of 0. look at
here and here
hop it help

Microsoft LUIS builtin.number

I used builtin.number in my LUIS app trying to collect a 4 digit pin number. The following is what's returned from LUIS when my input is "one two three four".
"entities": [
{
"entity": "one",
"type": "builtin.number",
"startIndex": 0,
"endIndex": 2,
"resolution": {
"value": "1"
}
},
{
"entity": "two",
"type": "builtin.number",
"startIndex": 4,
"endIndex": 6,
"resolution": {
"value": "2"
}
},
{
"entity": "three",
"type": "builtin.number",
"startIndex": 8,
"endIndex": 12,
"resolution": {
"value": "3"
}
},
{
"entity": "four",
"type": "builtin.number",
"startIndex": 14,
"endIndex": 17,
"resolution": {
"value": "4"
}
},
As you can see, it's returning individual digits in both text and digit format. Seems to me that it's more important to return the whole digit than the individual ones. Is there a way to do it so that I get '1234' as result for builtin.number?
Thanks!
It's not possible to do what you're asking for by only using LUIS. The way LUIS does its tokenization is that it recognizes each word/number individually due to the whitespace. It goes without saying that 'onetwothreefour' will also not return 1234.
Additionally, users are unable to modify the recognition of the prebuilt entities on an individual model level. The recognizers for certain languages are open-source, and contributions from the community are welcome.
All of that said, a way you could achieve what you're asking for is by concatenating the numbers. A JavaScript example might be something like the following:
var pin = '';
entities.forEach(entity => {
if (entity.type == 'builtin.number') {
pin += entity.resolution.value;
}
}
console.log(pin); // '1234'
After that you would need to perform your own handling/regexp, but I'll leave that to you. (after all, what if someone provides "seven eight nine ten"? Or "twenty seventeen"?)

Spring Redis sort keys

I have the following keys in Redis(Spring Data Redis),
localhost>Keys *
"1+ { \"_id":"1", \"Name\" : \"C5796\" , \"Site\" : \"DRG1\"}"
"2+ { \"_id":"2", \"Name\" : \"CX1XE\" , \"Site\" : \"DG1\"}"
"3+ { \"_id":"3", \"Name\" : \"C553\" , \"Site\" : \"DG1\"}"
If I want to sort according to id/name/site, how can I do it in Spring Redis?
List<Object> keys = redistemplate.sort(SortQueryBuilder.sort("Customer").build());
and,
SortQuery<String> sort = SortQueryBuilder.sort(key).noSort().get(field).build();
List<?> keys = redistemplate.boundHashOps(key).getOperations().sort(sort);
are not working.
The code is at the last of the post, if you are familiar with the principle of multi hset keys sort in redis, skip the following content and directly read the code.
Redis Sort is aimed to sort fields inside List/Set/Zset, but this method can be used to sort multi keys base on specified metric we want. We can use "sort" to sort multi hset keys by specified field, but there is limitation about the pattern of hset keys.
For example, if the pattern of hset keys is "hash{i}"(i is an integer), under this condition we can sort it.
127.0.0.1:6379> keys hash*
1) "hash3"
2) "hash2"
3) "hash1"
Take a look at the content of hash1:
127.0.0.1:6379> hgetall hash1
1) "id"
2) "24"
3) "name"
4) "kobe"
Every hash key contains two fields : "id", "name". If we want to sort these hset keys by its id. What should we do ?
First, add a set key named "myset". "myset" is a set key which contains members {"1", "2", "3"}.
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
Then run the following command:
127.0.0.1:6379> SORT myset BY hash*->id GET hash*->id GET hash*->name
1) "3"
2) "wade"
3) "24"
4) "kobe"
5) "30"
6) "curry"
Eureka, sort hash{1-3} by its id.
Here is the code of using Spring Redis to do the job:
public static String getRandomStr() {
return String.valueOf(new Random().nextInt(100));
}
public static void redisTemplateSort(RedisTemplate redisTemplate) {
String sortKey = "sortKey";
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(stringRedisSerializer);
redisTemplate.delete(sortKey);
if (!redisTemplate.hasKey(sortKey)) {
for (int i = 0; i < 10; i++) {
redisTemplate.boundSetOps(sortKey).add(String.valueOf(i));
String hashKey = "hash" + i,
strId = String.valueOf(i),
strName = getRandomStr(),
strSite = getRandomStr();
redisTemplate.boundHashOps(hashKey).put("_id", strId);
redisTemplate.boundHashOps(hashKey).put("Name", strName);
redisTemplate.boundHashOps(hashKey).put("Site", strSite);
System.out.printf("%s : {\"_id\": %s, \"Name\": %s, \"Site\", %s}\n",
hashKey, strId, strName, strSite);
}
}
SortQuery<String> sortQuery = SortQueryBuilder.sort(sortKey).by("hash*->Name")
.get("hash*->_id").get("hash*->Name").get("hash*->Site").build();
List<String> sortRslt = redisTemplate.sort(sortQuery);
for (int i = 0; i < sortRslt.size(); ) {
System.out.printf("{\"_id\": %s, \"Name\": %s, \"Site\", %s}\n", sortRslt.get(i+2), sortRslt.get(i+1), sortRslt.get(i));
i += 3;
}
}
Result of running redisTemplateSort(redisTemplate)(as sort by name in the code) :
hash0 : {"_id": 0, "Name": 59, "Site", 60}
hash1 : {"_id": 1, "Name": 37, "Site", 57}
hash2 : {"_id": 2, "Name": 6, "Site", 40}
hash3 : {"_id": 3, "Name": 91, "Site", 58}
hash4 : {"_id": 4, "Name": 39, "Site", 32}
hash5 : {"_id": 5, "Name": 27, "Site", 82}
hash6 : {"_id": 6, "Name": 43, "Site", 10}
hash7 : {"_id": 7, "Name": 17, "Site", 55}
hash8 : {"_id": 8, "Name": 14, "Site", 91}
hash9 : {"_id": 9, "Name": 39, "Site", 91}
{"_id": 40, "Name": 6, "Site", 2}
{"_id": 91, "Name": 14, "Site", 8}
{"_id": 55, "Name": 17, "Site", 7}
{"_id": 82, "Name": 27, "Site", 5}
{"_id": 57, "Name": 37, "Site", 1}
{"_id": 32, "Name": 39, "Site", 4}
{"_id": 91, "Name": 39, "Site", 9}
{"_id": 10, "Name": 43, "Site", 6}
{"_id": 60, "Name": 59, "Site", 0}
{"_id": 58, "Name": 91, "Site", 3}
I don't know about spring data redis. Let me give you a sample to achieve this in naive Redis. Let us say you have hash, which has id, name and site. and i have a list representing the keys of that hash.
My structure will be like :
lpush("Values",1);
hset("hash_1","id","1"),hset("hash_1","Name","C5796"),hset("hash_1","Site","DRG1")
for second hash
lpush("Values",2);
...
Similarly for all the values you want to set in hash. Now for sorting you do like this
SORT "Values" BY hash_*->id get hash_*->id get hash_*->name get hash_*->site
this will return you ascending sorted hashmaps result based on id. similarly you can do for names/site. For more info about sorting in redis : http://redis.io/commands/sort

Resources