Counting the characters of dictionary values inside a dataframe column - python

After downloading Facebook data, they provide json files with your post information. I read the json and dataframe with pandas. Now I want to count the characters of every post I made. The posts are in: df['data'] like: [{'post': 'Happy bday Raul'}].
I want the output to be the count of characters of: "Happy bday Raul" which will be 15 in this case or 7 in the case of "Morning" from [{'post': 'Morning'}].
df=pd.read_json('posts_1.json')
The columns are Date and Data with this format:
Date Data
01-01-2020 *[{'post': 'Morning'}]*
10-03-2020 *[{'post': 'Happy bday Raul'}]*
17-03-2020 *[{'post': 'This lockdown is sad'}]*
I tried to count the characters of this [{'post': 'Morning'}] by doing this
df['count']=df['data'].str.len()
But it's not working as result in "1".
I need to extract the value of the dictionary and do the len to count the characters. The output will be:
Date Data COUNT
01-01-2020 *[{'post': 'Morning'}]* 5
10-03-2020 *[{'post': 'Happy bday Raul'}]* 15
17-03-2020 *[{'post': 'This lockdown is sad'}]* 20
EDITED:
Used to_dict()
df11=df_post['data'].to_dict()
Output
{0: [{'post': 'Feliz cumpleaños Raul'}],
1: [{'post': 'Muchas felicidades Tere!!! Espero que todo vaya genial y siga aún mejor! Un beso desde la Escandinavia profunda'}],
2: [{'post': 'Hola!\nUna investigadora vendrá a finales de mayo, ¿Alguien tiene una habitación libre en su piso para ella? Many Thanks!'}],
3: [{'post': '¿Cómo va todo? Se que muchos estáis o estábais por Galicia :D\n\nOs recuerdo, el proceso de Matriculación tiene unos plazos concretos: desde el lunes 13 febrero hasta el viernes 24 de febrero.'}]
}

You can access the value of the post key for each row using list comprehension and count the length with str.len():
In one line of code, it would look like this:
df[1] = pd.Series([x['post'] for x in df[0]]).str.len()
This would also work, but I think it would be slower to execute:
df[1] = df[0].apply(lambda x: x['post']).str.len()
Full reproducible code below:
df = pd.DataFrame({0: [{'post': 'Feliz cumpleaños Raul'}],
1: [{'post': 'Muchas felicidades Tere!!! Espero que todo vaya genial y siga aún mejor! Un beso desde la Escandinavia profunda'}],
2: [{'post': 'Hola!\nUna investigadora vendrá a finales de mayo, ¿Alguien tiene una habitación libre en su piso para ella? Many Thanks!'}],
3: [{'post': '¿Cómo va todo? Se que muchos estáis o estábais por Galicia :D\n\nOs recuerdo, el proceso de Matriculación tiene unos plazos concretos: desde el lunes 13 febrero hasta el viernes 24 de febrero.'}]
})
df = df.T
df[1] = [x['post'] for x in df[0]]
df[2] = df[1].str.len()
df
Out[1]:
0 \
0 {'post': 'Feliz cumpleaños Raul'}
1 {'post': 'Muchas felicidades Tere!!! Espero qu...
2 {'post': 'Hola!
Una investigadora vendrá a fi...
3 {'post': '¿Cómo va todo? Se que muchos está...
1 2
0 Feliz cumpleaños Raul 22
1 Muchas felicidades Tere!!! Espero que todo vay... 112
2 Hola!\nUna investigadora vendrá a finales de ... 123
3 ¿Cómo va todo? Se que muchos estáis o está... 195

Related

Extract date from string in date format, add n number of days. to then replace with that modified data another substring within the original string

import re, datetime, time
input_text = "tras la aparicion del objeto misterioso el 2022-12-30 visitamos ese sitio nuevamente revisando detras de los arboles pero recien tras 3 dias ese objeto aparecio de nuevo tras 2 arboles" #example 1
input_text = "luego el 2022-11-15 fuimos nuevamente a dicho lugar pero nada ocurrio y 3 dias despues ese objeto aparecio en el cielo durante el atardecer de aquel dia de verano" #example 2
input_text = "Me entere del misterioso suceso ese 2022-11-01 y el 2022-11-15 fuimos al monte pero nada ocurrio, pero luego de 13 dias ese objeto aparecio en el cielo" #example 3
identified_referencial_date = r"(?P<year>\d*)-(?P<month>\d{2})-(?P<startDay>\d{2})" #obtained with regex capture groups
# r"(?:luego[\s|]*de[\s|]*unos|luego[\s|]*de|pasados[\s|]*ya[\s|]*unos|pasados[\s|]*unos|pasados[\s|]*ya|pasados|tras[\s|]*ya|tras)[\s|]*\d*[\s|]*(?:días|dias|día|dia)"
# r"\d*[\s|]*(?:días|dias|día|dia)[\s|]*(?:despues|luego)"
n = #the number of days that in this case should increase
indicated_date_relative_to_another = str(identified_date_in_date_format - datetime.timedelta(days = int(n) ))
input_text = re.sub(identified_referencial_date, indicated_date_relative_to_another, input_text)
print(repr(input_text)) # --> output
The objective is that if a day is indicated first in the format year-month-day (are integers separated by hyphens in that order) \d*-\d{2}-\d{2} and then it says that n amount of days have passed, so you would have to replace that sentence with year-month-day+n
luego de unos 3 dias ---> add 3 days to a previous date
luego de 6 dias ---> add 6 days to a previous date
pasados ya 13 dias ---> add 13 days to a previous date
pasados ya unos 48 dias ---> add 48 days to a previous date
pasados unos 36 dias ---> add 36 days to a previous date
pasados 9 dias ---> add 9 days to a previous date
tras ya 2 dias ---> add 2 days to a previous date
tras 32 dias ---> add 32 days to a previous date
3 dias despues ---> add 3 days to a previous date
3 dias luego ---> add 3 days to a previous date
Keep in mind that in certain cases, increasing the number of days could also change the number of the month or even the year, as in example 1.
Outputs that I need obtain in each case:
"tras la aparicion del objeto misterioso el 2022-12-30 visitamos ese sitio nuevamente revisando detras de los arboles pero recien 2023-01-02 ese objeto aparecio de nuevo tras 2 arboles" #for the example 1
"luego el 2022-11-15 fuimos nuevamente a dicho lugar pero nada ocurrio y 2022-11-18 ese objeto aparecio en el cielo durante el atardecer de aquel dia de verano" #for the example 2
"Me entere del misterioso suceso ese 2022-11-01 y el 2022-11-15 fuimos al monte pero nada ocurrio, pero 2022-11-28 ese objeto aparecio en el cielo" #for the example 3
Here is a regex solution you could use:
([12]\d{3}-[01]\d-[0-3]\d)(\D*?)(?:(?:luego de|pasados|tras)(?: ya)?(?: unos)? (\d+) dias|(\d+) dias (?:despues|luego))
This regex requires that there are no other digits between the date and the days. It also is a bit loose on grammar. It would also match "luego de ya 3 dias". You can of course make it more precise with a longer regex, but you get the picture.
In a program:
from datetime import datetime, timedelta
import re
def add(datestr, days):
return (datetime.strptime(datestr, "%Y-%m-%d")
+ timedelta(days=int(days))).strftime('%Y-%m-%d')
input_texts = [
"tras la aparicion del objeto misterioso el 2022-12-30 visitamos ese sitio nuevamente revisando detras de los arboles pero recien tras 3 dias ese objeto aparecio de nuevo tras 2 arboles",
"luego el 2022-11-15 fuimos nuevamente a dicho lugar pero nada ocurrio y 3 dias despues ese objeto aparecio en el cielo durante el atardecer de aquel dia de verano",
"Me entere del misterioso suceso ese 2022-11-01 y el 2022-11-15 fuimos al monte pero nada ocurrio, pero luego de 13 dias ese objeto aparecio en el cielo"
]
for input_text in input_texts:
result = re.sub(r"([12]\d{3}-[01]\d-[0-3]\d)(\D*?)(?:(?:luego de|pasados|tras)(?: ya)?(?: unos)? (\d+) dias|(\d+) dias (?:despues|luego))",
lambda m: m[1] + m[2] + add(m[1], m[3] or m[4]),
input_text)
print(result)

Why does this regex fail when trying to tell if there is a numeric character or more than one numeric character in the middle of a pattern?

import re
input_text = "hay alrededor de 4 coches el dia 7 del mes 5" #example 1
input_text = "Serian 4 unidades de mermelada para el dia 04 del 8 de este año 2023" #example 2
input_text = "Hay 10 unidades para el dia 15 del 12 y seran 9 ya para el 7 de noviembre" #example 3
input_text = "Hay 10 unidades para el 15 del 1º mes del año y seran alrededor de 9 para el 7º dia del mes de noviembre" #example 4
#for days
standard_number_of_digits_re_1 = r"(?:del dia|de el dia|el dia|del|de el|el)[\s|]*(\b\d{1}\b)"
standard_number_of_digits_re_2 = r"(\b\d{1}\b)[\s|]*º[\s|]*dia"
re_1_and_re_2 = r"(?:" + standard_number_of_digits_re_1 + r"|" + standard_number_of_digits_re_2 + r")"
#for months
#standard_number_of_digits_re_3 = re_1_and_re_2 + r"(?:del mes|de el mes|del|de el)[\s|]*(\b\d{1}\b)"
#standard_number_of_digits_re_4 = re_1_and_re_2 + r"(?:del mes|de el mes|del|de el)[\s|]*(\b\d{1}\b)[\s|]*(?:º[\s|]*mes del año|º[\s|]*mes)"
standard_number_of_digits_re_3 = r"(?:del mes|de el mes|del|de el)[\s|]*(\b\d)"
standard_number_of_digits_re_4 = r"(?:del mes|de el mes|del|de el)[\s|]*(\b\d)[\s|]*(?:º[\s|]*mes del año|º[\s|]*mes)"
#replacement with this conditions, and put '0' in front a day number only if it is one number and not two(or more numbers)
# example: '1' --> '01' or '10' --> '10'
input_text = re.sub(standard_number_of_digits_re_3, r"0\1", input_text)
input_text = re.sub(standard_number_of_digits_re_4, r"0\1", input_text)
input_text = re.sub(standard_number_of_digits_re_1, r"0\1", input_text)
input_text = re.sub(standard_number_of_digits_re_2, r"0\1", input_text)
print(repr(input_text)) #output
The problem I'm having is that the regex don't seem to work correctly since I can't do the replacements, but trying in several code editors I notice these 2 things:
In the Regex Debuger https://regex101.com/r/TfsKHZ/1 the regex appear to catch the correct text groups, but even so within the code they fail
In the SublimeText editor, when I put an r in front of "(?:" the whole line is immediately put as if it were a string of characters although you can see how this string is separated with operators in the middle in charge of the concatenation, however in StackOverflow that line is displayed correctly.
I do not know if these observations are important in the malfunction of these regex, but for some reason that I cannot find, the regex cannot extract the text to be edited by placing (if applicable) a 0 in front.
Leaving the output should be like this when printing them:
"hay alrededor de 4 coches el dia 07 del mes 05" #for example 1
"Serian 4 unidades de mermelada para el dia 04 del 08 de este año 2023" #for example 2
"Hay 10 unidades para el dia 15 del 12 y seran 9 ya para el 07 de noviembre" #for example 3
"Hay 10 unidades para el 15 del 01º mes del año y seran alrededor de 9 para el 07º dia del mes de noviembre" #for example 4
What modifications should I make to get these results? I think the problem is in this part of the regex (\b\d{1}\b)
Edited code
import re
input_text = "hay alrededor de 4 coches el dia 7 del mes 5" #example 1
#input_text = "Serian 4 unidades de mermelada para el dia 04 del 8 de este año 2023" #example 2
input_text = "Hay 10 unidades para el dia 15 del 12 y seran 9 ya para el 7 de noviembre" #example 3
#input_text = "Hay 10 unidades para el 15 del 1º mes del año y seran alrededor de 9 para el 7º dia del mes de noviembre" #example 4
#for days
standard_number_of_digits_re_1 = r"(?:del dia|de el dia|el dia|del|de el|el)[\s|]*(\b\d)"
standard_number_of_digits_re_2 = r"(\b\d)[\s|]*º[\s|]*dia"
#for months
standard_number_of_digits_re_3 = r"(?:del mes|de el mes|del|de el)[\s|]*(\b\d)"
standard_number_of_digits_re_4 = r"(?:del mes|de el mes|del|de el)[\s|]*(\b\d)[\s|]*(?:º[\s|]*mes del año|º[\s|]*mes)"
#replacement with this conditions, and put '0' in front a day number only if it is one number and not two(or more numbers)
# example: '1' --> '01' or '10' --> '10'
input_text = re.sub(standard_number_of_digits_re_3, r"0\1", input_text)
print(repr(input_text)) #output
input_text = re.sub(standard_number_of_digits_re_4, r"0\1", input_text)
print(repr(input_text)) #output
input_text = re.sub(standard_number_of_digits_re_1, r"0\1", input_text)
print(repr(input_text)) #output
input_text = re.sub(standard_number_of_digits_re_2, r"0\1", input_text)
print(repr(input_text)) #output
The problem is for example in the example 3 :
'Hay 10 unidades para 015 012 y seran 9 ya para 07 de noviembre'
And the correct output is:
'Hay 10 unidades para 15 12 y seran 9 ya para 07 de noviembre'
Get rid of \b after \d{1}. Python considers º to be a word character, so there's no word boundary between 7 and º. You don't need to match a word boundary, since the regexp only allows spaces or | between the number and º.
There's also no need for {1}. All patterns match 1 time unless they're quantified, so {1} is redundant.
(\b\d)[\s|]*º[\s|]*dia
https://regex101.com/r/84QDbp/1

Create patterns to detect the occurrence of sequences so that you can restrict in which cases to replace the detected substrings in the input string

These are the input string examples:
#example 1.1
colloquial_hour = "Hola nos vemos a las diez y veinte a m, ten en cuenta que al amanecer tendremos que estar despiertos, porque debemos estar alli a eso de nueve a m o las diez y cuarto a m"
#example 1.2
colloquial_hour = "A mi me parece entre las 10 15 am y las 11 a m, o a las 15 a m aunque quizas a medianoche este bien a eso de las 00:00 a m"
#example 1.3
colloquial_hour = "Puede que a las 10 am. Hay 10 a medias, a m mmm... creo que en 10 estarian para terminar a las 11:00 hs a m 11:59 a m"
#example 1.4
colloquial_hour = "Amediados a mediados del 30 antes de y dia; me parace que hay que estar en casa. Medianamente a, mediados de las 05 a m o cerca de 6 a m."
I have tried with a simple replacement, but I think that the cases must be further restricted with a regex pattern so that unwanted replacements are not made...
colloquial_hour = colloquial_hour.replace('a m', 'am ')
, and to be able to obtain this string as output...
the correct output for each of these examples:
#example 1.1
colloquial_hour = "Hola nos vemos a las diez y veinte am, ten en cuenta que al amanecer tendremos que estar despiertos, porque debemos estar alli a eso de nueve am o las diez y cuarto am"
#example 1.2
colloquial_hour = "A mi me parece entre las 10 15 am y las 11 am, o a las 15 am aunque quizas a medianoche este bien a eso de las 00:00 am"
#example 1.3
colloquial_hour = "Puede que a las 10 am. Hay 10 a medias, a m mmm... creo que en 10 estarian para terminar a las 11:00 hs am 11:59 am"
#example 1.4
colloquial_hour = "Amediados a mediados del 30 antes de y dia; me parace que hay que estar en casa. Medianamente a, mediados de las 05 am o cerca de 6 am."
In this case, the pseudo-pattern is:
some number "a m" to replace with the string "am" one or more empty spaces, a period, a comma or directly the end of the string
Cases should also be considered where there may be incompletely written schedules where "am" would be preceded by ":", " :", ": ", " hs", "hs", "hs ", " h.s. ", "h.s.", "h.s. ", " h.s", "h.s" or "h.s " , for example,
input_t = "a las 12: a m"
output = "a las 12: am"
input_t = "a las 12 : a m"
output = "a las 12 : am"
input_t = "a las 12 hs a m"
output = "a las 12 hs am"
input_t = "a las 12:hs a m"
output = "a las 12:hs am"
input_t = "a las 12: hs a m"
output = "a las 12: hs am"
input_t = "a las 12hsa m"
output = "a las 12hs am"
input_t = "a las 12h.sa m"
output = "a las 12h.s am"
input_t = "a las 12 h.sa m"
output = "a las 12 h.s am"
input_t = "a las 12 h.s.a m"
output = "a las 12 h.s. am"
For the first part I made this regex:
out = re.sub(r"([0-9][0-9]\W)a m(\W|\b)", r"\1am\2", colloquial_hour)
It change the "a m" for "am" keeping whatever was before and after.
For the "hs" or "h.s" I did this:
out = re.sub(r"(hs|h.s)(\.)?\W*a m(\W|\b)", r"\1\2 am\3", out)
It search for "hs", "h.s" before "a m". You can combine both regex, they are pretty similar or use them sequentially.
Let me know if there is any problem.

Save rows of a text in a dictionary

I'm web scraping to get information about articles from a website, for that text I want to save the header of the text and the description as key and value in a dictionary.
When I run the code, I get an error unhashable type: 'list'. What I can do to fix this?
This is all the code:
import requests
import bs4
from bs4 import BeautifulSoup
import smtplib
import os
bodyDict = dict()
newslist = list()
body = "NEWS:\n"
web = requests.get("http://www.infobolsa.es/news")
soup = bs4.BeautifulSoup(web.text, 'lxml')
for item in soup.find_all("article"):
newslist.append(item.text.split("\n"))
for row in newslist:
bodyDict[newslist[1]]=newslist[3]
print(bodyDict)
This can be achieved using the code below. We need to get the header (in <h3> tags) and the value (in the last <p>) tag for each <article> tag in the page. I've assumed that you want to ignore header tags that have the class 'video'.
import requests
import bs4
bodyDict = dict()
web = requests.get("http://www.infobolsa.es/news")
soup = bs4.BeautifulSoup(web.text, 'lxml')
for item in soup.find_all("article"):
# Find the header
header = item.find('h3')
# Ignore headers that are videos
if 'video' in header.get('class', []):
continue
# Get the value of the last p tag
value = item.find_all('p')[-1].text
# Append to dictionary
bodyDict[header.text] = value
Which gives us:
{'PharmaMar recibe 200 millones de dólares como pago inicial del acuerdo firmado con Jazz': 'PharmaMar y Jazz firmaron el pasado 19 de diciembre de 2019 un acuerdo de licencia en exclusiva para la comercialización de lurbinectedina en Estados Unidos.\xa0PharmaMar también podrá recibir hasta 800 millones de dólares adicionales en potenciales pagos por hitos, además de los royalties sobre las ventas netas.',
'El Ibex 35, el índice con mayor fortaleza de Europa hoy': 'Los índices europeos y sus futuros, futuro del Dax y futuro del Euro Stoxx 50, a media mañana están con subidas, pero han perdido el rumbo y están a la espera de lo que pueda hacer el futuro del SP500 que les sirva de\xa0 guía para tomar una dirección. El Ibex 35 es el más destacado gracias a que el Banco Santander lidera las subidas (+3,68%).',
'Eurostoxx 50: primer objetivo 3.730 puntos': 'Ángel Cotera, especialista de mercados de BBVA Trader analiza desde un punto de vista técnico el Eurostoxx 50.',
'Grenergy tiene la confianza de Caixabank y su recomendación de compra': 'Los analistas otorgan un precio objetivo\xa0de 18,65 euros la compañía de renovables, lo que supone un recorrido alcista del 21,10% para los títulos de la\xa0compañía de energías renovables en el Mercado Continuo.',
'UBS eleva la recomendación de Bankinter en un momento correctivo en bolsa': 'El organismo cree que con el mínimo histórico al que cotizan actualmente la acciones cualquier riesgo está "mejor reflejado". Sube su recomendación hasta neutral.',
'La FED afronta su primera reunión del año sin la presión de los mercados ni de Trump': 'Juan Ramón Casanovas, Head of Private Portfolio Management, Bank Degroof Petercam Spain valora las opciones que tiene Jerome Powell en la primera reunión de la FED del año.',
'PharmaMar tendrá en China la tecnología para detectar el coronavirus en 6 semanas': 'La biotecnológica española cuenta con la tecnología para detectar el virus y está trabajando para adaptar las máquinas\xa0de diagnóstico de Genomica con las que cuenta en Wuhan.',
'Airbus provisiona 3.600 millones para pagar posibles sanciones por corrupción': 'Airbus ha provisionado\xa03.600 millones de euros\xa0para el pago de posibles sanciones a las autoridades francesas, británicas y estadounidenses. Las investigaciones emprendidas por dichas autoridades conciernen a acusaciones de soborno y de corrupción así como a imprecisiones en declaraciones hechas a las autoridades de los Estados Unidos de acuerdo con el International Traffic in Arms Regulations (ITAR).',
'Logista aumenta su beneficio un 3,3% hasta los 37,2 millones': 'El distribuidor de productos minoristas Logista alcanzó un beneficio neto en su\xa0primer trimestre fiscal\xa0del año (octubre-diciembre) de 37,2 millones de euros, lo que supone un aumento del 3,3%.',
'Santander solo aspira a rebotes a corto plazo': 'Santander continúa inmerso en una clara tendencia bajista de largo plazo que permanece vigente mientras el precio no consiga superar 3,9395 / 3,8655. Si el precio consigue respetar los mínimos del año pasado y el volumen aumenta se avanzaría en la construcción de un suelo. \xa0',
'Banco Santander lleva al Ibex 35 por encima de los 9.500 puntos': 'El Ibex 35 arranca la sesión con subidas del 0,49% que le llevan a los 9.532 puntos. Subidas que lideran los títulos de Banco\xa0 Santander que, tras la publicación de sus resultados, ha llegado a subir más de un 3% en la apertura.',
'El mayor banco de Canadá sobrepondera ahora las acciones de Repsol': 'Los analistas de\xa0Royal Bank of Canada (RBC) han elevado este miércoles\xa0la recomendación de Repsol de "infraponderar" hasta\xa0"sobreponderar", ya que según el mayor banco canadiense\xa0la petrolera española ha empezado a mostrar una mejor relación riesgo-rentabilidad que la mayoría de sus\xa0competidoras.',
'Las bolsas europeas abren con tono mixto pendientes de China y la FED': 'Los índices de las principales bolsas europeas comienzan la sesión con tono mxixto. El DAX sube un 0,04%, hasta los 13.328 puntos; el FTSE -100 arranca la sesión con subidas del 0,13%, hasta los 7.491 puntos. El CAC-40 abre en los 5.926 pntos mientras que el Eurostoxx 50 abre en los 3.722 puntos tras avanzar ligeramente. El FTSE MiB en negativo sobre los 24.024 puntos. Hoy toda la atención sobre China y la primera reunión del año de la FED.',
'Banco Santander reduce un 17% su beneficio en 2019, hasta los 6.515 millones': 'Banco Santander ha anunciado una reducción del 17% en su beneficio atribuido en 2019, hasta los 6.515 millones. Y eso a pesar de que en el cuarto trimestre la entidad incrementó en un 35% su beneficio logrando así el mayor beneficio atribuido de la historia, en los 2.783 millones. La compañía propone aumentar el dividendo en efecto.',
'MAB: ventajas de las empresas al cotizar en Bolsa': 'Las pymes son actrices protagonistas de la economía española. Sólo alguien que no sepa de economía las consideraría actrices de reparto, ya que emplean al 80% de nuestra fuerza laboral y representan el 65% de nuestro PIB. Cuando necesitan financiación, visibilidad, liquidez, y el resto de ventajas que conlleva cotizar, disponen de una plataforma hecha a su medida: el Mercado Alternativo Bursátil (MaB). Sus integrantes volverían a dar el salto sin dudarlo, pero se quejan de que le siguen faltando tamaño y, por ende, liquidez.',
'Tesla sigue alcista tras superar en Bolsa a Volkswagen': '\xa0',
'"Los sectores más atractivos y que más nos gustan son los más caros: tecnología y salud"': 'Hablamos de los mercados con Josep Bayarri, director de productos, análisis e inversiones de Arquia Banca.\xa0',
'"Creemos que es más fácil, en un año como este, invertir en pequeñas y medianas compañías"': 'Hablamos de los mercados y para ello contamos con la presencia de Álvaro de Liniers, responsable de desarrollo de negocio de Groupama AM para España.',
'Reunión de la Fed y resultados de Logista y Santander, en la agenda del día': 'Este miércoles los inversores y analistas estarán muy pendientes del índice de confianza del consumidor Gfk, decisión de tipos de interés de la Fed, variación de ventas de viviendas pendientes y conferencia de prensa de la\xa0Comité Federal del Mercado Abierto de la Reserva Federal.'}

How to fix this regex in order to preserve a given id order?

I have this large string:
s = '''Vaya ir VMM03S0 0.427083
mañanita mañana RG 0.796611
, , Fc 1
buscando buscar VMG0000 1
la lo PP3FSA00 0.0277039
encontramos encontrar VMIP1P0 0.65
. . Fp 1
Pero pero CC 0.999764
vamos ir VMIP1P0 0.655914
a a SPS00 0.996023
lo el DA0NS0 0.457533
que que PR0CN000 0.562517
interesa interesar VMIP3S0 0.994868
LO_QUE_INTERESA_La lo_que_interesa_la NP00000 1
lavadora lavador AQ0FS0 0.585262
tiene tener VMIP3S0 1
una uno DI0FS0 0.951575
clasificación clasificación NCFS000 1
A+ a+ NP00000 1
, , Fc 1
de de SPS00 0.999984
las el DA0FP0 0.970954
que que PR0CN000 0.562517
ahorran ahorrar VMIP3P0 1
energía energía NCFS000 1
, , Fc 1
si si CS 0.99954
me me PP1CS000 0.89124
no no RN 0.998134
equivoco equivocar VMIP1S0 1
. . Fp 1
Lava lavar VMIP3S0 0.397388
hasta hasta SPS00 0.957698
7 7 Z 1
kg kilogramo NCMN000 1
, , Fc 1
no no RN 0.998134
está estar VAIP3S0 0.999201
, , Fc 1
se se P00CN000 0.465639
le le PP3CSD00 1
veía ver VMII3S0 0.62272
un uno DI0MS0 0.987295
gran gran AQ0CS0 1
tambor tambor NCMS000 1
( ( Fpa 1
de de SPS00 0.999984
acero acero NCMS000 0.973481
inoxidable inoxidable AQ0CS0 1
) ) Fpt 1
y y CC 0.999962
un uno DI0MS0 0.987295
error error NCFSD23 0.234930
error error VMDFG34 0.98763
consumo consumo NCMS000 0.948927
máximo máximo AQ0MS0 0.986111
de de SPS00 0.999984
49 49 Z 1
litros litro NCMP000 1
error error DI0S3DF 1
Mandos mandos NP00000 1
intuitivos intuitivo AQ0MP0 1
, , Fc 1
todo todo PI0MS000 0.43165
muy muy RG 1
bien bien RG 0.902728
explicado explicar VMP00SM 1
, , Fc 1
jamas jamas RG 0.343443
nada nada PI0CS000 0.850279
que que PR0CN000 0.562517
de de SPS00 0.999984
nunca nunca RG 0.903
casa casa NCFS000 0.979058
de de SPS00 0.999984
mis mi DP1CPS 0.995868
error error VM9032 0.234323
string string VMWEOO 0.03444
padres padre NCMP000 1
Además además NP00000 1
incluye incluir VMIP3S0 0.994868
la el DA0FS0 0.972269
tecnología tecnología NCFS000 1
error errpr RG2303 1
Textileprotec textileprotec NP00000 1
que que PR0CN000 0.562517
protege proteger VMIP3S0 0.994868
nuestras nuestro DP1FPP 0.994186
ninguna ninguno DI0S3DF 0.345344
falla falla NCFSD23 1
prendas prenda NCFP000 0.95625
más más RG 1
preciadas preciar VMP00PF 1
jamas jamas RG2303 1
string string VM9032 0.234323
nunca nunca RG 0.293030
string string VM 0.902333
no no RN
le le PP004DF 0.390230
falla fallar VM0FD00 0.99033
. . Fp 1'''
I would like to extract in a list the second word from left to right and its id that holds this ids pattern: RN_ _ _ _ _, PP_ _ _ _ _, VM_ _ _ _ _. This ids must be together. For example:
no no RN 0.90383
le le PPSDF23 0.902339
falla fallar VM00DKE 0.9045
This is the pattern I would like to match, since they are together and the ids have the RN_ _ _ _ _, PP_ _ _ _ _, VM_ _ _ _ _ order this should be the output given the s string:
[('no RN', 'le PP004DF', 'fallar VM0FD00')]
This is what I tried:
together__ = re.findall(r'(?s)(\w+\s+RN)(?:(?!\s(?:RN|PP|VM)).)*?(\w+\s+PP\w+)(?:(?!\s(?:RN|PP|VM)).)*?(\w+\s+VM\w+)', s)
but I get this with the above regex:
print together__
output:
[('no RN', 'le PP3CSD00', 'ver VMII3S0'), ('no RN', 'le PP004DF', 'fallar VM0FD00')]
Which is wrong since the ids are not consecutevely in the string s (RN, PP, VM). How can I fix this regex?. Thanks in advance guys.
You better
You can do this simply with:
list = re.findall(r'\n?\s*\S+\s+(\w+\W+RN\w*)[^\n]*[^\n]*?\n\s*\S+\s+(\w+\W+PP\w*)[^\n]*[^\n]*?\n\s*\S+\s+(\w+\W+VM\w*)[^\n]*', s)
Resulting in:
[('no RN', 'le PP004DF', 'fallar VM0FD00')]
because ver VM is first.
In case you don't get a decent answer soon enough, I think that I may be close to what you want with this:
re.findall(r'\n[^\n]*?\s(.*?\sRN[^\n]*)\n[^\n]*?\s(.*?\sPP[^\n]*)\n[^\n]*?\s(.*?\sVM[^\n]*)\n', s)
I don't know why I get both words in the first item... might be because of the "#" and I did not bother cutting after RN, PP and VM. I guess that if the first step works decently enough, the rest can be easily fixed in post-processing.

Categories