# Text Processing - MOSAIQ Medical Notes

**URL:** <https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314>\
**Category:** KNIME Analytics Platform\
**Created:** [January 1, 2024, 9:53pm UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314 "2024-01-01T21:53:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![AAM](https://forum-cdn.knime.com/user_avatar/forum.knime.com/aam/32/44417_2.png) [@AAM](https://forum.knime.com/u/AAM)\
**Post date:** [January 1, 2024, 9:53pm UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/1 "2024-01-01T21:53:29Z")

</div>

Happy New Year KNIMErs!

I am moving into processing text entries in our OIS (MOSAIQ). Many moons ago I tried to get our dietitians to enter their assessments into pre-formatted assessments but they resisted and continued to enter their dietary assessment as free, though partially formatted, text. I am looking to extract this data and analyse.

I have pulled all of the Notes which contain the text “_DIETITAN - Initial Assessment_” into a table which includes **Pat\_ID1** (patient identifier), **Notes** (the entered text) and **Create\_DtTm** (Date of Note Creation). The text below is a typical free text entry. It is all deidentified.

```auto
DIETITIAN - Initial Assessment
Head & Neck Cancer Support and Therapy Clinic: multidisciplinary review attended (CNC, Dietitian, Sp Path). ISBAR Clinical Handover received from A.Miller (31/10/23). Three points ID confirmed, consented. Attended with friend.
Dx: FOM SCC pT4aN1M0
Treatment: ant segmental mandibulectomy + bilateral ND + free flap recon (R fibular donor site, dental implants) 18/9/23
- planning for adj CRT
- RIG insertion planned 29/11/23
Medical History: haemachromatosis (3/12 venesections), benign brain tumour excised 2018, hypercholesterolaemia, high ETOH (pre-op 2-3 bottles wine/d)
Social/Activity: lives alone - supportive family and friends locally

Anthropometry:
Weight: 51.6kg (clinic scales)	
Height: 173.1cm (MOSAIQ)	
Physical Assessment: moderate-severe muscle and fat deficits globally
BMI: 17.2kg/m2 (underwt, HWR 18.5-25)
Weight History: UBW 57kg - 12-13% LOW in 4mths pre-op
- 1.9kg increase in 2-3 weeks

Biochemistry: 26/10 Cr 41L, eGFR >90, alb 34N
Clinical: 
- ceased smoking since Sx adm, significant reduction in ETOH
- NGT removed day of d/c (30/10/23)
- oral stinging with intake, tolerating minced/mashed consistency
- oral spillage, oral feeding slow
- good appetite

Estimated Nutrition requirements (51.6kg)
Energy: 1290-1550kcals/d (25-30kcals/kg) maintenance + 500kcals/d wt gain allowance = 1790-2050kcals/d
Protein: 60-65g/day (1.2g/kg)
Fluid: 1800mL/day (35ml/kg)

Diet: 
- texture: minced/mashed diet, thin fluids
- supplementation: 5x200ml Ensure TwoCalHN (84g protein, 2000kcals, 705mls fluid)
- intake: 3 small meals - combined diet and supplementation providing ~120g protein, ~2500-2600kcals
- fluid: ~1900mls/d

Assessment:
PG-SGA = B13
Moderately MALNOURISHED but demonstrating clinical improvement as evidenced by
- wt gain in 2 weeks on background of severe LOW (remains underwt BMI)
- tolerating adequate intake orally with substantial contribution from ONS
- meeting wt gain allowance

Negotiated Goal/s: 
- continue supplementation to facilitate wt gain

Recommendations:  
1. continue HPHE minced/mashed diet 
2. 3-5 x 200ml Ensure TwoCalHN
- encouraged to titrate volume according to diet tolerance / avoid displacing diet intake by satiating with ONS

Plan: RIG education post SIM
Contact 555-555-555

```

I wish to be able to do two things:

1. extract relevant variables, such as:

```auto
Weight: 51.6kg (clinic scales)

```

To get a feel for the process, I wish to do something simple (for you, hard for me!):

a. find the text “Weight:” inside **Notes** [I can do this already]  
b. extract the following text up to and including the letters “kg”  
c. export the text " 51.6kg" into a column named Weight  
d. have an associated column for **Create\_DtTm**

1. substitute text

For example, expand ‘underwt’ into ‘underweight’

---

<div class="post-metadata">

**Author:** ![ArjenEX](https://forum-cdn.knime.com/letter_avatar_proxy/v4/letter/a/97f17d/32.png) [@ArjenEX](https://forum.knime.com/u/ArjenEX)\
**Post date:** [January 1, 2024, 10:33pm UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/2 "2024-01-01T22:33:33Z")

</div>

Hi @AAM

Regarding extracting the weight, I would go with a **Regex Extractor** and use lookahead/lookbehind queries, like `(?<=Weight: )([0-9.]+[k][g])`

 ![image](https://forum-cdn.knime.com/uploads/default/original/3X/6/0/601db3521cffa2bdda4ca7d47756a09ff1b1969b.png)

Available here if you don’t already have it: [Regex Extractor — NodePit](https://nodepit.com/node/ws.palladian.nodes.extraction.regex2.RegexExtractor2NodeFactory)

> [@AAM](#):
>
> d. have an associated column for **Create\_DtTm**

This is hard to understand. You mention earlier that you already have **Create\_DtTm** in a table, so what’s the additional requirement here?

Regarding text substitution, it really depends on how many replacements you are looking at. If it’s just a few, you can build a nested `replace()` function. Otherwise you are looking into more complex solutions.

> **[Recursive replacement in strings based on a replacement dictionary – knime](https://hub.knime.com/knime/spaces/Examples/06_Control_Structures/04_Loops/08_Example_for_Recursive_Replacement_of_Strings~MjiD7VtF32L8KI8X/current-state)**
>
> In this workflow strings, defined in a replacement table (or dictionary) will be replaced in strings that are contained in a second data table in a recursive w…

---

<div class="post-metadata">

**Author:** ![AAM](https://forum-cdn.knime.com/user_avatar/forum.knime.com/aam/32/44417_2.png) [@AAM](https://forum.knime.com/u/AAM)\
**Post date:** [January 2, 2024, 4:10am UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/3 "2024-01-02T04:10:26Z")

</div>

@ArjenEX,

Many thanks. I’ll try those things to get going on the project.

You are correct about the **Create\_dtTm** , it doesn’t need any manipulation. I was just including it for completeness’ sake,

Good start to 2024!

A

---

<div class="post-metadata">

**Author:** ![AAM](https://forum-cdn.knime.com/user_avatar/forum.knime.com/aam/32/44417_2.png) [@AAM](https://forum.knime.com/u/AAM)\
**Post date:** [January 2, 2024, 8:02am UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/4 "2024-01-02T08:02:06Z")

</div>

> [@ArjenEX](#):
>
> (?\<=Weight: )([0-9.]+[k][g])

It does work @ArjenEX!

The node returns **Full Match** and **Group 1**. How do you change the names of those new columns?-  
[**COMPLETED, no answer needed**] use:

```auto
\b(?<Weight>?<=Weight: )([0-9.]+[k][g])\b

```

Is there a node which will do multiple extractions, e.g., Weight, Height, PG-SGA, etc? I expect there is some way of using a loop with a list of regex commands for each loop, but that his well out of my pay grade.

A

---

<div class="post-metadata">

**Author:** ![ArjenEX](https://forum-cdn.knime.com/letter_avatar_proxy/v4/letter/a/97f17d/32.png) [@ArjenEX](https://forum.knime.com/u/ArjenEX)\
**Post date:** [January 2, 2024, 9:41am UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/5 "2024-01-02T09:41:42Z")

</div>

Hi @AAM

It really depends on your use case what method works best. A simple way to do this is by building a combined Regex that separates each property by an OR statement (`|`)

Like:  
`(Weight:[0-9.]+[k][g])|(Height:[0-9.]+[c][m])|(BMI:[0-9.]+[kg/m2]+)`

 ![image](https://forum-cdn.knime.com/uploads/default/original/3X/a/6/a6a1b157f4336dde8262e20c62faf2146ff309bb.png)

Exclude the full match and set the output type as `List`. Then use a column collection splitter to retrieve the individual values.

 ![image](https://forum-cdn.knime.com/uploads/default/original/3X/e/e/ee4ef91aee9d312893bd9e341d839353affde25d.png)

The downside of the above method is that, assume that for whatever reason one of the targeted fields is not present in the note, it will shift everything to the left so the same properties might not be in the same column. The upside is that it’s only one node only and easy to manage.

 ![image](https://forum-cdn.knime.com/uploads/default/original/3X/9/c/9c7bd5befd082bedf6f395523e19896baf9407f2.png)

If it’s only a few parameters, you can also just put a few Regex Extractors in sequence and use the syntax you established before.

---

<div class="post-metadata">

**Author:** ![AAM](https://forum-cdn.knime.com/user_avatar/forum.knime.com/aam/32/44417_2.png) [@AAM](https://forum.knime.com/u/AAM)\
**Post date:** [January 2, 2024, 10:19am UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/6 "2024-01-02T10:19:20Z")

</div>

@ArlyKen I am very appreciative and very humbled by your solution. I shall trial and adapt and do wonderful things with the data!

Many thanks again,

A

---

<div class="post-metadata">

**Author:** ![mlauber71](https://forum-cdn.knime.com/user_avatar/forum.knime.com/mlauber71/32/73590_2.png) [@mlauber71](https://forum.knime.com/u/mlauber71)\
**Post date:** [January 2, 2024, 4:57pm UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/7 "2024-01-02T16:57:48Z")

</div>

@AAM you could also employ ChatGPT to let it write Regex statements for you. If your texts are to a certain extent ‘standard’ RegEx will be a good way forward.

Another option could be to use a large language model to extract the informations. One challenge will be to get the data back always in the same format.

---

<div class="post-metadata">

**Author:** ![system](https://forum-cdn.knime.com/uploads/default/original/1X/ab3ccf34482a0329361734a18199390177204f15.png) [@system](https://forum.knime.com/u/system)\
**Post date:** [April 1, 2024, 4:58pm UTC](https://forum.knime.com/t/text-processing-mosaiq-medical-notes/76314/8 "2024-04-01T16:58:38Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
