3
$\begingroup$

This question is about finding names of people in a text without knowing these people. There are some rules we can use to detecting names in a text

  1. A name consist always of two or more words (example : Luke Morgan, Rosemary van Gogh)

  2. The surname and family names always start with a capital.

  3. There can be a insertion between surname and famaly name. These parts of the name can be written as single charachters followed by a dot (like George v.d. king"). Or these parts of the name are seperated words like "van" or "de". These parts mormale written not in capitals.

  4. After the famaly name there is a blanc or a comma

  5. The surname can be written as one or more capitals each followed by a dot (example : M.A. van Mens or M.A. v. Mens of M. A. van Mens)

  6. The surname and family name can start at the beginning of a new line

In the text below, there are four names: "Michiel A. van Mens", "Gerrit van de Veen", "Keesje Kwak" en "Henk de Leegt". But, can we find them?

text1 = "Lorem ipsum Michiel A. van Mens, Gerrit van de Veen dolor \ sit amet,consectetur adipiscing elit. Aliquam blandit, quam id Keesje \ Kwak ultricies, ligula leo iaculis erat,non malesuada risus leo quis \ dolor.Donec a fermentum mauris.Sed nec quam porttitor,posuere lorem \ vel,egestas orci. Phasellus aliquet pharetra massa, ut hendrerit arcu \ tincidunt ut. Mauris pulvinar volutpat augue, in blandit dolor \ euismod id. Ut mattis turpis metus, sed laoreet velit consequat sit \ amet. Nulla pharetra lectus vitae augue vehicula dapibus. Quisque \ venenatis sem at risus Henk de Leegt molestie. Curabitur et ultrices \ sapien. Suspendisse consequat metus erat,eu faucibus dui aliquam ac."

To find the names, I wrote this code:

text2 = TextCases[text1, "Sentence"];
text3 = Flatten[
  StringSplit[StringReplace[text2, WordBoundary ~~ "," -> "|"], "|"]];

famnaam = {};

For [k = 1, k <= Length[test1], k++,
  naampos = 
   StringPosition[test1[[k]], 
    StringCases[test1[[k]], RegularExpression["[A-Z]\\S+"]]];
  pos = {};
  For
   [i = 1, i < Length[naampos], i++,
   If[naampos[[i + 1, 1]] - naampos[[i, 2]] <= 10,
     AppendTo[pos, {naampos[[i, 1]], naampos[[i + 1, 2]]}]
      ];
   ];
  AppendTo[famnaam, StringTake[test1[[k]], pos]];
  ];

Flatten[DeleteCases[famnaam,  ""]]

The output is: {"De heer Michiel", "Michiel A.", "A. van Mens", "Gerrit van de Veen", "Keesje Kwak", "Henk de Leegt"}. As you can see, this script couldn't find my own name.

The WL expert JP Tollenboom wrote me an alternative:

words = DeleteCases[StringSplit[text1, {" ", ".", ",", ";"}], ""];

im = Module[{c},
     c = StringTake[#, 1];
     If[c == ToUpperCase[c], "1", "0"]
     ] & /@ words;

imj = StringJoin[im]

His approuche is based on the position of the Capitals

output: "101101100100000010001100000000000100010000000010000000010000000010000\ 0000010000001000010101000100000000"

extract[char_String] :=
 Module[{pos, seq},
  pos = StringPosition[imj, char] // Flatten;
  seq = Range[pos[[1]], pos[[1]] - 1 + StringLength[char]]; Echo[seq];
  Extract[words, Partition[seq, 1]]
  ]

extract["1101"]

output: {3,4,5,6}. {"Michiel", "van", "Mens"}

Questions: do you know a better solutions or can you improve the codes (to find for example more complexe names)

$\endgroup$
  • $\begingroup$ Search for „Named Entity Recognition“ $\endgroup$ – Sascha Jan 23 '18 at 15:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.