gnames / gndiff

GNdiff compares scientific names from two files
MIT License
5 stars 1 forks source link

first impressions and questions #13

Open abubelinha opened 2 years ago

abubelinha commented 2 years ago

First of all, thanks a lot for creating gndiff. It's gonna be so useful for me.

I have just tried with a small file, to get the feeling of how it works. I already found some issues to comment:

EDIT: I have just realized that some of the above suggestions were already addressed by @Adafede in a previous closed issue (#12). Sorry about that. My comments are pretty verbose, so @dimus might still find some helpful feedback in some of them. This is a new one:

Thanks a lot in advance !!

abubelinha commented 2 years ago

To illustrate a bit more my results above, I will paste the example 2 of my previous comment (I provided an empty family in reference.csv):

gndiff_source.csv : (A, B, C added here for reference: they were not part of the file)

ScientificName
A. Obione maritima (Alfredo) Pacino var. maritimaa
B. Obione maritima (Alfredo) Di'Stefano subsp. maritima
C. Quercus lamarkensis

gndiff_reference.csv :

TaxonID,Family,ScientificName
1001,,Obione maritima (Alfredo) Pacino var. maritima
1002,,Obione maritima (Alfredo) Pacino subsp. maritima

It is a minimal example, but I want to illustrate that my reference list wouldn't be a simple list of very different accepted names. Actually, it will include very similar names which might be or not synonymous of other names in the same list (acceptedID is of course missing in the example).

TEST 1: JSON

*** COMMAND: C:\gnames\gndiff gndiff_source.csv gndiff_reference.csv -f pretty
*** OUTPUT: (
 {
  "Matches": [
    {
      "sourceRecord": {
        "dataSet": "gndiff_source",
        "index": 1,
        "name": "Obione maritima (Alfredo) Pacino var. maritimaa"
      },
      "referenceRecords": [
        {
          "dataSet": "gndiff_reference",
          "index": 1,
          "editDistance": 1,
          "id": "1001",
          "name": "Obione maritima (Alfredo) Pacino var. maritima",
          "matchType": "Fuzzy"
        },
        {
          "dataSet": "gndiff_reference",
          "index": 2,
          "editDistance": 1,
          "id": "1002",
          "name": "Obione maritima (Alfredo) Pacino subsp. maritima",
          "matchType": "Fuzzy"
        },
        {
          "dataSet": "gndiff_reference",
          "index": 1,
          "editDistance": 1,
          "id": "1001",
          "name": "Obione maritima (Alfredo) Pacino var. maritima",
          "matchType": "Fuzzy"
        },
        {
          "dataSet": "gndiff_reference",
          "index": 2,
          "editDistance": 1,
          "id": "1002",
          "name": "Obione maritima (Alfredo) Pacino subsp. maritima",
          "matchType": "Fuzzy"
        }
      ]
    },
    {
      "sourceRecord": {
        "dataSet": "gndiff_source",
        "index": 2,
        "name": "Obione maritima (Alfredo) Di'Stefano subsp. maritima"
      },
      "referenceRecords": [
        {
          "dataSet": "gndiff_reference",
          "index": 1,
          "id": "1001",
          "name": "Obione maritima (Alfredo) Pacino var. maritima",
          "matchType": "Exact"
        },
        {
          "dataSet": "gndiff_reference",
          "index": 2,
          "id": "1002",
          "name": "Obione maritima (Alfredo) Pacino subsp. maritima",
          "matchType": "Exact"
        }
      ]
    },
    {
      "sourceRecord": {
        "dataSet": "gndiff_source",
        "index": 3,
        "name": "Quercus lamarkensis"
      },
      "referenceRecords": null
    }
  ]
}

TEST 2: CSV

*** COMMAND: C:\gnames\gndiff gndiff_source.csv gndiff_reference.csv -f csv**
*** OUTPUT:
 gndiff_source,1,,Obione maritima (Alfredo) Pacino var. maritimaa,gndiff_reference,Fuzzy,1,1001,Obione maritima (Alfredo) Pacino var. maritima,1
gndiff_source,1,,Obione maritima (Alfredo) Pacino var. maritimaa,gndiff_reference,Fuzzy,2,1002,Obione maritima (Alfredo) Pacino subsp. maritima,1
gndiff_source,1,,Obione maritima (Alfredo) Pacino var. maritimaa,gndiff_reference,Fuzzy,1,1001,Obione maritima (Alfredo) Pacino var. maritima,1
gndiff_source,1,,Obione maritima (Alfredo) Pacino var. maritimaa,gndiff_reference,Fuzzy,2,1002,Obione maritima (Alfredo) Pacino subsp. maritima,1
gndiff_source,2,,Obione maritima (Alfredo) Di'Stefano subsp. maritima,gndiff_reference,Exact,1,1001,Obione maritima (Alfredo) Pacino var. maritima,0
gndiff_source,2,,Obione maritima (Alfredo) Di'Stefano subsp. maritima,gndiff_reference,Exact,2,1002,Obione maritima (Alfredo) Pacino subsp. maritima,0
gndiff_source,3,,Quercus lamarkensis,,NoMatch,,,,

*** COMMAND: c:\gnames\gndiff -V
version: v0.1.1
build:   2021-12-28_02:44:39UTC

COMMENTS:

  1. Why do I get up to 4 matches for name A (sourceRecord.index=1), when my reference.csv only has 2 rows? Looks like all Fuzzy matches are simply repeated twice? Why do all of them have an editDistance=1? I would expect name 1001 (rank var.) to have a different value than 1002 (rank subsp.), because the searched name is has subspecific rank.

  2. Why do I get "Exact" matches for name B (sourceRecord.index=2, rank subsp.), if its authors are different to those of both reference.csv names?
    I would expect a Fuzzy match, where name 1002 (rank subsp.) should be a closer match than name 1001 (rank var.). Is it possible to have some numeric output information (similar to editDistance) which lets me make a decision to select name 1002 over 1001?

  3. As I reported above, CSV output is a bit confusing without headers. For example, I can't figure out the meaning of the numeric values (0 | 1) in the right column.

I am mostly concerned about the possibilities of getting the "best choice" in 1 & 2. But there are no numeric differences which could help in that task (specially when editDistance is not available). I only found info about the editDistance in the source code. Is there a detailed explanation of this value somewhere?
I guess it is only calculated for fuzzy matches, but I couldn't figure out how different 2 names should be in order to get a different editDistance value (i.e. 0.8, 0.9) ... can I see some examples? I tried some variations but couldn't produce a value different to 1.

Biased by my little experience with other gnames applications, I expected gndiff JSON output to be much more verbose than it is. (as an option, at least). As names are being parsed for the matching process, I would be interested in taking profit of the parsed stuff in my output (for both source.csv and reference.csv names). I miss many fields which could help us to make decisions when several matches are found:

Of course, I mention all this because I assume all that info is actually being generated during gndiff matching process. So it wouldn't be difficult to (optionally) output everything, I hope.

So, to summarize FEATURE REQUESTS:

Sorry for the long explanations. I hope some of all this verbosity makes sense.

Thanks a lot for all your help, and sorry for not having tested gndiff much earlier (got some problems receiving github email notifications, so I missed many things during the last month)

dimus commented 2 years ago

@abubelinha, I got back to gndiff finally and going through your comment.

I will try to modify README according to your notes and answers to other topics are below. Also see new opened issues. If something is missing, please create a new issue (one per topic), if something is there but needs to be refined, please add your feedback there.

  1. Fields from source

Names to be matched (source.csv), might also contain their own ids, but it is unclear to me whether gndiff is suggesting user to provide them or not

It is definitely a possibility. I suspect a good approach would be to keep all fields from the source, and just enough fields from the reference (as it is now). I can make it as an option.

Source can have any number of fields, same as reference.

Field 'Family' is not implemented yet. If it is given in both files, it will be showsn for both files.

  1. Output bug

If I don't provide a Family column in reference.csv, then json output referenceRecords[n].family contains the same value as name (the ScientificName field provided in my reference.csv file).

This is a bug, I will make an issue

  1. Family field and the speed of execution.

No effect on speed at all. Families just show in the output for manual comparison by the user.

  1. Calculated score

yes, it does make sense. Currently score is used only for sorting results, it also can be set to return a value like in resolver.

  1. Why do I get up to 4 matches for name A (sourceRecord.index=1), when my reference.csv only has 2 rows?

Sounds like a bug

  1. Why do I get "Exact" matches for name B (sourceRecord.index=2, rank subsp.), if its authors are different to those of both reference.csv names?

Exact match is made by canonical forms, and authorship is used to pick better results.

  1. Why "subsp" get "var" as best result:

It is a bug, I have to find out why it happens.

  1. More verbose output in JSON, parser data.a

Makes sense, I'll make a ticket.

  1. Edit distance is a Levenshtein edit distance between simple canonical forms.

  2. Run it as a server with resource list preloaded.

Interesting idea, yes, can be done too.

@abubelinha, thank you a lot for your feedback, a lot of good ideas and bug reports.

abubelinha commented 2 years ago

You're welcome. Thanks a lot to you indeed for all your awesome work