User Tools

Site Tools


medicacion2021

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
medicacion2021 [2021/03/28 13:37]
osotolongo [Reglas]
medicacion2021 [2021/04/03 10:39]
osotolongo [Aplicando las reglas]
Line 1: Line 1:
 ====== Informe de medicacion ====== ====== Informe de medicacion ======
  
 +Ver programas en github: https://github.com/asqwerty666/medica
 +
 +===== tl;dr =====
 +
 +<code bash>
 +$ ./parse.pl medicamentos.db
 +$ ./apply_rules.pl -r med_rules_ed_0219.txt
 +</code>
 +
 +Y ahora lee al menos acerca del formato de input. ;-)
 ===== Antes de empezar ===== ===== Antes de empezar =====
  
Line 23: Line 33:
 Asi que hacemos, Asi que hacemos,
 <code bash> <code bash>
-[osotolongo@brick03 medicacion]$ awk -F";" '{print $2";"$4";"$7}' anamnesi.csv | sed 's/,/ /g;s/-//g' > anamnesi.db +[osotolongo@brick03 medicacion]$ awk -F";" '{print $2";"$4";"$7}' anamnesi.csv | sed 's/-//;s/-//' > anamnesi.db 
 </code> </code>
  
Line 29: Line 39:
  
 <code bash> <code bash>
-[osotolongo@brick03 medica]$ head anamnesi.db+[osotolongo@brick03 medica]$ head anamnesi.db 
 Interno;Fecha_A_DN_EXN;Recetas_SIRE Interno;Fecha_A_DN_EXN;Recetas_SIRE
 19960001;19970430; 19960001;19970430;
-19960003;19960129;Boik Seguril Plurimen Aremis 50 100 Masdil Tensoprem +19960003;19960129;Boi-k Seguril Plurimen Aremis 50 1-0-0 Masdil Tensoprem 
-19960004;19960101;Meleril 50 Distraneurine Cisordimol 005 Nerdipina 111 +19960004;19960101;Meleril 50 Distraneurine Cisordimol 0-0-5 Nerdipina 1-1-1 
-19960006;19960117;Escazine 100 Remontal 111 Ciclofalina 330 Meleril 555 Aneurol si precisa Hidroferol 1 al m‚s+19960006;19960117;Escazine 1-0-0 Remontal 1-1-1 Ciclofalina 3-3-0 Meleril 5-5-5 Aneurol si precisa Hidroferol 1 al m‚s
 19960008;19960129; 19960008;19960129;
 19960009;19960116;Eskazine 2mg cada 8 hores Largactil intramuscular en cas d'agitaci¢ 19960009;19960116;Eskazine 2mg cada 8 hores Largactil intramuscular en cas d'agitaci¢
Line 43: Line 53:
  
 ---- ----
-**Ojo aqui:** El comando //awk// selecciona lsolo las columnas que necesitamos. Esto incluye el //ID//, la fecha de cada visita y el texto libre que se scribe en la receta. A las fechas le estoy quitando el caracter //-// y de texto libre estoy quitando las comas por si me introducen ruido. De este ultimo campo hay todavia mucha porqu ria que quitar pero eso lo voy a hace en el parser directamente.+**Ojo aqui:** El comando //awk// selecciona lsolo las columnas que necesitamos. Esto incluye el //ID//, la fecha de cada visita y el texto libre que se escribe en la receta. A las fechas le estoy quitando el caracter //-// y el texto libre lo dejo tal cual. De este ultimo campo hay mucha porqueria que quitar pero eso lo voy a hacer en el parser directamente.
 ---- ----
  
Line 65: Line 75:
  
 <code bash> <code bash>
-[osotolongo@brick03 medicacion]$ awk -F";" '{print $1";"$2";"$5}' seguimientos.csv | sed 's/,/ /g;s/-//g' > seguimientos.db +[osotolongo@brick03 medicacion]$ awk -F";" '{print $1";"$2";"$5}' seguimientos.csv | sed 's/-//g;s/-//g' > seguimientos.db 
 </code> </code>
  
Line 71: Line 81:
  
 <code bash> <code bash>
-[osotolongo@brick03 medica]$ head seguimientos.db+[osotolongo@brick03 medica]$ head seguimientos.db 
 Interno;FechaSeguiment;Receta_SIRE_SN Interno;FechaSeguiment;Receta_SIRE_SN
 19960014;19981217; 19960014;19981217;
-19960044;20050314;igual: tegretol:1/200+19960044;20050314;igual: tegretol:1/2-0-0
 19960068;19990713; 19960068;19990713;
-19960171;20100331;Reminyl 24 mgr LR 100  Axura 20 mgr  Omeprazol 20 mgr 100  Pazital  Nerdipina 101  Prevencor 010   Sumial 10 mgr  Sedotime 001   Plavix 010+19960171;20100331;Reminyl 24 mgr LR 1-0-0, Axura 20 mgrOmeprazol 20 mgr 1-0-0, PazitalNerdipina 1-0-1, Prevencor 0-1-0,  Sumial 10 mgrSedotime 0-0-1 , Plavix 0-1-0
-19960171;20110329;Dormicum   Esertia 10 mgr   Pantoprazol  Plavix   Reminyl   Simvastatina   Sumial Seroquel 100 mgr +19960171;20110329;Dormicum Esertia 10 mgr PantoprazolPlavix Reminyl Simvastatina Sumial Seroquel 100 mgr 
-19960171;20120203;Alprazolam 0.25 mgr  Dormicum 7.5 mgr  Esertia 10 mgr   Pantoprazol   Plavix  Reminyl 24 mgr   Seroquel 200 111  Sinvastatina 20 mgr 100  Ebixa 20 mgr 100 +19960171;20120203;Alprazolam 0.25 mgrDormicum 7.5 mgrEsertia 10 mgr Pantoprazol PlavixReminyl 24 mgr Seroquel 200 1-1-1, Sinvastatina 20 mgr 1-0-0, Ebixa 20 mgr 1-0-0 
-19960171;20121108;Alprazolam 0.25 mgr  Dormicum 7.5 mgr Mirtazapina 10 mgr   Pantoprazol   Plavix Seroquel 100 111  Sinvastatina 20 mgr 100  Ebixa 20 mgr 100  Keppra 250 101 +19960171;20121108;Alprazolam 0.25 mgrDormicum 7.5 mgr,Mirtazapina 10 mgr Pantoprazol Plavix,Seroquel 100 1-1-1, Sinvastatina 20 mgr 1-0-0, Ebixa 20 mgr 1-0-0, Keppra 250 1-0-1 
-19960171;20130627;Alprazolam   Dormicum   Duphalac   Ebixa 20 mgr   Keppra 250 mgr   Misrtazapina 30 mgr   Pantoprazol   Plavix  Seroquel 100 mgr 111  Sinvastatina +19960171;20130627;Alprazolam Dormicum Duphalac Ebixa 20 mgr Keppra 250 mgr Misrtazapina 30 mgr Pantoprazol PlavixSeroquel 100 mgr 1-1-1, Sinvastatina 
-19960171;20140701;Adiro 100 mgr   Alprazolam 0.25 mgr   Dormicum 7.5 mgr   Duphalac   Keppra 250 mgr y 500 mgr   Pantoprazol 20 mgr   Seroquel 100 mgr 111  Sinvastatina 10 mgr+19960171;20140701;Adiro 100 mgr Alprazolam 0.25 mgr Dormicum 7.5 mgr Duphalac Keppra 250 mgr y 500 mgr Pantoprazol 20 mgr Seroquel 100 mgr 1-1-1, Sinvastatina 10 mgr
 </code> </code>
  
Line 104: Line 114:
   - Es muy sencillo insertar un envio de email al final del script   - Es muy sencillo insertar un envio de email al final del script
  
-**No medicamenteos:** Como la mayor parte de la limpieza la voy a hacer con expresiones regulares, voy a tomar el archivo //stopwords_orange.txt// que contiene un grupo grande de cadenas de caracteres que **no** son medicamentos y voy a quitar todos lo numeros. tras esto, quito las lineas que queden en blanco o que esten repetidas.+**No medicamentos:** Como la mayor parte de la limpieza la voy a hacer con expresiones regulares, voy a tomar el archivo //stopwords_orange.txt// que contiene un grupo grande de cadenas de caracteres que **no** son medicamentos y voy a quitar todos lo numeros. Tras esto, quito las lineas que queden en blanco o que esten repetidas.
  
 <code bash> <code bash>
Line 110: Line 120:
 </code> </code>
  
-Ahora, este archivo lo necesito de input para el parser. Lo voy a convertir en un //array// y despues solo tengo que quitar estas palabras cada vez que las encuentre. O algo parecido. Asi que dentro del codigo edbo incluir,+Ahora, este archivo lo necesito de input para el parser. Lo voy a convertir en un //array// y despues solo tengo que quitar estas palabras cada vez que las encuentre. O algo parecido. Asi que dentro del codigo debo incluir,
  
 <code perl> <code perl>
Line 170: Line 180:
 </code> </code>
  
-lo que me ha queado es una base de datos supuestamente limpia aunque aun deberia contener palabras que no son medicamentos. Voy a escribirla a disco,+lo que me ha quedado es una base de datos supuestamente limpia aunque aun deberia contener palabras que no son medicamentos. Voy a escribirla a disco,
  
 <code perl> <code perl>
Line 234: Line 244:
 </code> </code>
  
 +**Ahora, las reglas han de revisarse y editarse a mano. Esto no hay manera de evitarlo pero solo ha de hacerse una vez. La proxima vez que se haga el analisis se usara el mismo archivo de reglas.**
 +
 +===== Reglas de CIMA =====
 +
 +https://cima.aemps.es/cima/publico/nomenclator.html
 +
 +Me bajo la lista de medicamentos comercializados en España y la convierto a CSV. Luego hago esto:
 +
 +<code bash>
 +[osotolongo@brick03 medicaion_dev]$ awk -F";" '{print $2}' Medicamentos.csv | tail -n +2 | sed 's/\// /g' |awk '{print $1}' | tr '[:upper:]' '[:lower:]' | sort | uniq > medicamentos.list
 +</code>
 +
 +O si quiero tener los principios activos,
 +
 +<code bash>
 +[osotolongo@brick03 medicaion_dev]$ awk -F";" '{print $2";"$8";"$9}' Medicamentos.csv | tail -n +2 | sed 's/\// /g' | tr '[:upper:]' '[:lower:]' | sort | uniq | sed 's/\.//g' > medicamentos_pa.list
 +[osotolongo@brick03 medicaion_dev]$ sed 's/\([^ ]*\).*;\(.*\);\(.*\)/\1;\2;\3/' medicamentos_pa.list | uniq > mpa.list
 +</code>
 +
 +
 +===== Aplicando las reglas =====
 +
 +Aqui he de leer tres cosas antes que nada. Primero, las reglas que hemos construido. Estas las voy a asignar a un hash de arrays,
 +
 +<code perl>
 +my %wrules;
 +open RDF, "<$rules_file" or die "No rules file";
 +while (<RDF>){
 +        (my $rkey, my $rvalue) = /^(\w*): (.*)$/;
 +        chomp $rvalue;
 +        my @lpat = split /\|/, $rvalue;
 +        %{$wrules{$rkey}} = map {$_ => 1} @lpat unless !$rkey;
 +}
 +close RDF;
 +
 +</code>
 +
 +Luego, la lista de principios activos de [[https://cima.aemps.es/cima/publico/home.html|CIMA]].
 +
 +<code perl>
 +my %cima;
 +open ADF, "<$mpa";
 +while (<ADF>){
 +        my ($med, $pal, $pan) = /^(.*);(.*);(.*)$/;
 +        my @pas = split /, /, $pal;
 +        for (@pas) {s/\s+/_/g;}
 +        $cima{$med} = [ @pas ];
 +}
 +close ADF;
 +</code>
 +
 +
 +Ahora cargo base de datos ya revisada, que si todo va bien sera el output del script anterior.
 +
 +<code perl>
 +my $dbfile = 'parsed_meds.csv';
 +
 +my %visits;
 +my %meds;
 +open IDF, "<$dbfile" or die "Database file do not exists\n";
 +while(<IDF>){
 +        my ($pid, $vid, $ldata) = /^(\d+);(\d+);(.*)$/;
 +</code>
 +
 +Pero voy a ir llenando el hash de output (// %visits //) a medida que leo. Primero meto toda la medicacion de la visita en un array,
 +
 +<code perl>
 +        if($ldata){
 +                my @mlist = split /,/, $ldata;
 +</code>
 +
 +y ahora, para cada elemento de este array, recorro las reglas, buscando si este termino existe dentro de alguna regla. 
 +
 +<code perl>
 +                foreach my $med (@mlist){
 +                        if ($med){
 +                                foreach my $rkey (sort keys %wrules){
 +                                        if(exists($wrules{$rkey}{$med})){
 +                                                foreach my $pa (@{$cima{$rkey}}){
 +                                                        $meds{$pa} = 1;
 +                                                        $visits{$pid}{$vid}{$pa} = 1;
 +                                                }
 +                                                last;
 +                                        }
 +                                }
 +                        }
 +                }
 +</code>
 +
 +Cuando encuentro este elemento en las reglas, marco tods los ID de principios activos correspondientes a este medicamento como existentes en esa visita y ademas los sumo a las variables que he de escribir. Si no se encuentra este termino, se concluye que no es ningun medicamento (pues no esta en ninguna regla) y no se hace nada.
 +
 +Una vez llenados los medicamentos de cada visita hemos de escribirlo en forma matricial. Primero escribimos los headers,
 +
 +<code perl>
 + open ODF, ">$ofile" or die "Could not open file !!!!!!\n";
 +print ODF "Interno,Fecha_visita";
 +foreach my $med (sort keys %meds){
 +        print ODF ",$med";
 +}
 +print ODF "\n";
 +</code>
 +
 +Y ahora llenamos los valores correspondientes a cada visita con un 1, caso de existir y un 0 en caso contrario.
 +
 +<code perl>
 +foreach my $pid (sort keys %visits){
 +        foreach my $vid (sort keys %{$visits{$pid}}){
 +                print ODF "$pid,$vid";
 +                foreach my $med (sort keys %meds){
 +                        if(exists($visits{$pid}{$vid}{$med})){
 +                                print ODF ",1";
 +                        }else{
 +                                print ODF ",0";
 +                        }
 +                }
 +                print ODF "\n";
 +        }
 +}
 +close ODF;
 +</code>
 +
 +**TADA!**
  
medicacion2021.txt · Last modified: 2021/04/03 10:42 by osotolongo