Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

For a Natural Language Processing analysis task it's desirable to highlight a text string programmatically according to XML tags that reference specific words or phrases.

The XML tags specify the character ranges in the input string as well as give other information such as identifiers and other codes.

Since character ranges are provided in the XML markup, originally I thought StringReplacePart would do the job, but it doesn't seem possible to transform the string into more general expressions, eg using Subscript or Style.

For example (please excuse I'm showing only a fragment due to Protected Health Information), given the (partial) input text:

In[566]:= StringTake[I2B2[1, text], -500]

Out[566]= " pain and was treated with Percocet . She went for a \
debridement of her left calf lesion on 10/2/93 and was started \
empirically on IV ceftriaxone which was changed to po doxycycline on \
the day of discharge . A follow-up CT scan was done which did not \
show any evidence for splenomegaly or hepatomegaly . The 1 cm cyst \
which was seen in 10/92 was still present . There was a question of a \
cyst in her kidney with a stone right below the cyst , although this \
did not seem to be clinically significant ."

And the XML tag:

In[581]:= Cases[I2B2[1, tags], 
 XMLElement[
  "EVENT", {id_, start_, end_, text_ -> "a stone", modality_, 
   polarity_, type_}, _]]

Out[581]= {XMLElement[
  "EVENT", {"id" -> "E75", "start" -> "2476", "end" -> "2483", 
   "text" -> "a stone", "modality" -> "POSSIBLE", "polarity" -> "POS",
    "type" -> "PROBLEM"}, {}]}

The following StringReplacePart works (to ALL CAPS) since the output is still a string:

In[577]:=  StringReplacePart[
 StringTake[I2B2[1, text], -500],
 "A STONE", {2476, 
   2483 - 1} - ((I2B2[1, text] // StringLength ) - 500)]

Out[577]= " pain and was treated with Percocet . She went for a \
debridement of her left calf lesion on 10/2/93 and was started \
empirically on IV ceftriaxone which was changed to po doxycycline on \
the day of discharge . A follow-up CT scan was done which did not \
show any evidence for splenomegaly or hepatomegaly . The 1 cm cyst \
which was seen in 10/92 was still present . There was a question of a \
cyst in her kidney with A STONE right below the cyst , although this \
did not seem to be clinically significant ."

But the following does not since I'm trying to highlight in Red using Style:

In[578]:=  StringReplacePart[
 StringTake[I2B2[1, text], -500],
 Style["a stone", 
  Red], {2476, 2483 - 1} - ((I2B2[1, text] // StringLength ) - 500)]

Out[578]= StringReplacePart[" pain and was treated with Percocet . \
She went for a debridement of her left calf lesion on 10/2/93 and was \
started empirically on IV ceftriaxone which was changed to po \
doxycycline on the day of discharge . A follow-up CT scan was done \
which did not show any evidence for splenomegaly or hepatomegaly . \
The 1 cm cyst which was seen in 10/92 was still present . There was a \
question of a cyst in her kidney with a stone right below the cyst , \
although this did not seem to be clinically significant .", \!\(\*
StyleBox["\<\"a stone\"\>",
StripOnInput->False,
LineColor->RGBColor[1, 0, 0],
FrontFaceColor->RGBColor[1, 0, 0],
BackFaceColor->RGBColor[1, 0, 0],
GraphicsColor->RGBColor[1, 0, 0],
FontColor->RGBColor[1, 0, 0]]\), {413, 419}]

Are there functions similar to StringReplacePart that can output more general expressions? Or in any case how to perform the desired highlighting with Subscript and Style?

share|improve this question
    
This is a potentially very deep question. While styling a single section of a string (which becomes a Row) is trivial, styling multiple sections, potentially overlapping, becomes far from trivial. –  Mr.Wizard Jun 30 '12 at 22:25
add comment

3 Answers

up vote 5 down vote accepted

As far as I know you can't put style information in strings themselves. They're just a bunch of characters from a character table. You can style the output of a string, but not put that in a string itself. So, StringReplacePart doesn't make sense here.

You could solve it as follows:

Row[{"There was a question of a cyst in her kidney with", 
      Style[" a stone", Red], 
      " right below the cyst , although this did not seem to be clinically significant ."}]

Mathematica graphics

or you could think of working in low-level StyleBox-es.

You could use StringSplit to split the string around "a stone", or use StringPosition and StringTake.

share|improve this answer
    
Thanks Sjoerd. StringSplit can't be used here because repeated substrings can have unique identifiers. StringTake followed by extracting the complementary ranges and sort them before applying Row works: complementaryRanges = Cases[ ReplacePart[(# - {0, 1}) & /@ Partition[ Drop[Flatten[ SortBy[Join[events[[All, 1]], timex[[All, 1]]], #[[1]] &]], 1], 2, 2, 1], {-1, 2} -> StringLength[I2B2[1, text]]], {s_, e_} /; e > s];Row[Last /@ SortBy[Join[events, timex, {#, StringTake[I2B2[file, text], #]} & /@ complementaryRanges], #[[1]] &]] –  alancalvitti Jul 1 '12 at 20:00
add comment

I needed some similar task that it was basically about, take a whatever text ( a string) and replace or highlighting some word or list of words with color, to notice them. I did this:

texto = "Este seńor JUANCHO, al ver a este seńor al cual yo estaba \
asdfasdf, viendo que asdfadsfasdf, entonces me llama por \
teléfono a la casa y me dice"

palabra = "en";

Row[Riffle[StringSplit[texto, palabra ], 
  Style[palabra, Red, FontWeight -> Bold]]]

enter image description here

share|improve this answer
    
Very nice and compact, thank you. What if you had multiple distinct substrings to highlight in different colors? –  alancalvitti Aug 26 '13 at 15:53
    
Actually, I should do that with a list, so I use a iterative For over List, and with !StringFreeQ of regular expression from word in List, highlight it. –  d555 Aug 27 '13 at 18:06
add comment

I think you can use StyleBox in a String like this:

"\*StyleBox[\"a stone\", FontColor->RGBColor[1, 0, 0]]"

which will give a result the same as Style["a stone", Red].

Note you should specify color by RGBColor[...] but not Red, I think the reason is the same as this post.

Edit:

A more complicated example with SubscriptBox:

StringReplacePart["1234567890",
           "\*StyleBox[\!\(XXXX\_2\),FontColor->RGBColor[1,0,0]]",
                  {5, 7}]

Boxes have special form in String, you can use ToString[exp,form] to get them:

ToString[
         Style[
               HoldForm[
                        Sum[(Derivative[k][f][0]/k!)*x^k, {k, 0, Infinity}]
                       ],
               FontFamily -> "Times"],
         TraditionalForm]//FullForm
share|improve this answer
    
Thanks Silvia, that offers another way to go about it. I ultimately coded it using StringTake but that involved additional code to select complementary ranges and sorting. –  alancalvitti Jul 1 '12 at 19:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.