csv.reader fooled by line terminators inside data fields - python

I have a CSV file downloaded from the internet that I need to parse. Python with the csv.reader seems to be the tool of choice, however my input has line terminators (both \r and \n) inside some data fields. This makes for incomplete lines. The field data are surrounded by apostrophes so the issue ought to be avoidable - but how?
I tried with and without the dialect='excel', no difference. I know I need to apply iconv to my input data, too.
import csv
with open(INFILNAM,'rb') as csvfile:
infil = csv.reader(csvfile, dialect='excel', delimiter=';', quotechar='"')
for row in infil:
print ', '.join(row)
Sample of the output, "aaa " preceeding each line for clarity:
aaa , LF0121, La Trancli�re, Base ULM Acc�s priv�, 9/03/2011, 20/02/2012, 20/02/2012, 46.095556, 5.286667, N 46 05 44, E 005 17 12, 820 ft, Tour de piste imp�ratif du c�t� autoroute. Ne pas voler au dessus du village de la Trancli�re. Presque toujours d�gag�., 1, herbe, '36, 40, 640, '18-36, , , , , , 123.5, , , , roger.emeriat#wanadoo.fr, +33 4 74 46 84 34, Village le plus proche : essence , hotels, etc = Pont D'ain � 4, 5 km. En cas de brume : altiport de corlier a environ 15 km
aaa
aaa Infos suppl�mentaires : Laurent Pradel St� Vectral. repr�sentant appareil savannah dans la r�gion. Possibilit� essai de l'appareil en vol. T�l : 04 74 35 60 00 email vectral#wanadoo.fr,
aaa , LF0125, Lavours, Base ULM Autorisation OBLIGATOIRE , 8/03/2011, 24/06/2015, 25/06/2015, 45.795, 5.77361099999996, N 45 47 42, E 005 46 25, 768 ft, TDP � l'est
aaa Eviter les villages en rouge sur la photo, faire la vent-arri�re sur le Rh�ne.
aaa attention aux rouleaux par vent de travers, 1, herbe, '01, 20, 450, '01-19, herbe, , , , 'Inconnue, 123.5, , , , , +33 4 79 42 11 57, attention, base Hydro ULM club de Lavours � proximit� ,
aaa , LF0151, Corbonod Seyssel, A�rodrome Priv� Avec Restrictions Autorisation OBLIGATOIRE , 6/09/2011, 10/01/2015, 11/01/2015, 45.960629840733, 5.817818641662598, N 45 57 38, E 005 49 04, 1175 ft, Arriv�e dans axe de la piste puis, du centre vent arri�re main gauche
aaa Suivre le plan imperatif (photo jointe), 1, dur, '01, 15, 400, '01-19, herbe, , , , 'Inconnue, 123.5, , 6, Restauration � proximit�, dudunoyer#yahoo.fr, +33 6 07 38 20 15, PPR obligatoire pour tous,ULM et avion (arr�t� pr�fectoral). Contacter le Pdt de l'AAC gestionnaire.

The file is being parsed fine; the new lines are just being printed again in your print statement.
Replacing print ', '.join(row) with print row gives the following output:
['Obsol\xe8te', 'Code terrain', 'Toponyme', 'Type', 'Date creation', 'Derni\xe8re modification', 'Date validation', 'Position', 'Latitude', 'Longitude', 'Altitude', 'Consignes', 'Nombre de pistes', 'Nature premi\xe8re piste', 'Axe pr\xe9f\xe9rentiel premi\xe8re piste', 'Largeur premi\xe8re piste', 'Longueur premi\xe8re piste', 'Orientation premi\xe8re piste', 'Nature deuxi\xe8me piste', 'Axe pr\xe9f\xe9rentiel deuxi\xe8me piste', 'Largeur deuxi\xe8me piste', 'Longueur deuxi\xe8me piste', 'Orientation deuxi\xe8me piste', 'Radio', 'Carburant', 'Facilit\xe9s', 'Facilit\xe9s en clair', 'Email de contact', 'T\xe9l\xe9phone', 'Informations compl\xe9mentaires']
['', 'LF0121', 'La Trancli\xe8re', 'Base ULM Acc\xe8s priv\xe9', '8/03/2011', '6/09/2015', '12/09/2015', '46.095556, 5.286667', 'N 46 05 44', 'E 005 17 12', '820 ft', 'Tour de piste imp\xe9ratif du c\xf4t\xe9 autoroute. Ne pas voler au dessus du village de la Trancli\xe8re. Presque toujours d\xe9gag\xe9.', '1', 'herbe', "'36", '40', '640', "'18-36", 'herbe', '', '', '', "'Inconnue", '123.5', '', '', '', 'roger.emeriat#wanadoo.fr', '+33 4 74 46 84 34', "Village le plus proche : essence , hotels, etc = Pont D'ain \xe0 4, 5 km. En cas de brume : altiport de Corlier a environ 15 km\r\r\r\n\r\nInfos suppl\xe9mentaires : Laurent Pradel St\xe9 Vectral. repr\xe9sentant appareil savannah dans la r\xe9gion. Possibilit\xe9 essai de l'appareil en vol. T\xe9l : 04 74 35 60 00 email vectral#wanadoo.fr", '']
['', 'LF0125', 'Lavours', 'Base ULM Autorisation OBLIGATOIRE ', '8/03/2011', '24/06/2015', '25/06/2015', '45.795, 5.77361099999996', 'N 45 47 42', 'E 005 46 25', '768 ft', "TDP \xe0 l'est\r\r\nEviter les villages en rouge sur la photo, faire la vent-arri\xe8re sur le Rh\xf4ne.\r\r\nattention aux rouleaux par vent de travers", '1', 'herbe', "'01", '20', '450', "'01-19", 'herbe', '', '', '', "'Inconnue", '123.5', '', '', '', '', '+33 4 79 42 11 57', 'attention, base Hydro ULM club de Lavours \xe0 proximit\xe9 ', '']
['', 'LF0151', 'Corbonod Seyssel', 'A\xe9rodrome Priv\xe9 Avec Restrictions Autorisation OBLIGATOIRE ', '6/09/2011', '10/01/2015', '11/01/2015', '45.960629840733, 5.817818641662598', 'N 45 57 38', 'E 005 49 04', '1175 ft', 'Arriv\xe9e dans axe de la piste puis, du centre vent arri\xe8re main gauche \r\r\nSuivre le plan imperatif (photo jointe)', '1', 'dur', "'01", '15', '400', "'01-19", 'herbe', '', '', '', "'Inconnue", '123.5', '', '6', 'Restauration \xe0 proximit\xe9', 'dudunoyer#yahoo.fr', '+33 6 07 38 20 15', "PPR obligatoire pour tous,ULM et avion (arr\xeat\xe9 pr\xe9fectoral). Contacter le Pdt de l'AAC gestionnaire.\r\r\nRadio obligatoire pour tous + qualif montagne souhait\xe9e pour avion. Interdit ULM classe 1\r\r\nSurvol interdit \xe0 l'Est du Rh\xf4ne entre Seyssel et Culoz: Zone Biotope Natura 2000\r\r\n\xc9colage et TDP interdit\r\r\nRadio 123.5 car piste l\xe9g\xe8rement convexe.\r\r\r\n\r\nCamping 1.5 KM\r\r\nResto + h\xf4tel : 2Km", '']
As you can see, the new lines within quotes have not created new rows.

Related

Add substring at specified position within a string if a pattern is identified in it except for the absence of that substring which should be complete

import re, datetime
input_text = 'del dia 10 a las 10:00 am hasta el 15 de noviembre de 2020' #example 1
input_text = 'de el 10 hasta el 15 a las 20:00 pm de noviembre del año 2020' #example 2
input_text = 'desde el 10 hasta el 15 de noviembre del año 2020' #example 3
input_text = 'del 10 a las 10:00 am hasta el 15 a las 20:00 pm de noviembre de 2020' #example 4
identificate_day_or_month = r"\b(\d{1,2})\b"
identificate_hours = r"[\s|]*(\d{1,2}):(\d{1,2})[\s|]*(?:a.m.|a.m|am|p.m.|p.m|pm)[\s|]*"
months = r"(?:enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|este mes|mes que viene|siguiente mes|mes siguiente|mes pasado|pasado mes|anterior año|mes anterior)"
identificate_years = r"(?:del[\s|]*del[\s|]*año|de[\s|]*el[\s|]*año|del[\s|]*del[\s|]*ano|de[\s|]*el[\s|]*ano|del|de)[\s|]*(?:el|)[\s|]*(?:este[\s|]*año[\s|]*\d*|este[\s|]*año|año[\s|]*que[\s|]*viene|siguiente[\s|]*año|año[\s|]*siguiente|año[\s|]*pasado|pasado[\s|]*año|anterior[\s|]*año|año[\s|]*anterior|este[\s|]*ano[\s|]*\d*|este[\s|]*ano|ano[\s|]*que[\s|]*viene|siguiente[\s|]*ano|ano[\s|]*siguiente|ano[\s|]*pasado|pasado[\s|]*ano|anterior[\s|]*ano|ano[\s|]*anterior|este[\s|]*\d*|año \d*|ano \d*|el \d*|\d*)"
#Identification pattern conformed to the sequence of characters with which I am trying to define the search pattern
identification_re_0 = r"(?:(?<=\s)|^)(?:desde[\s|]*el|desde|del|de[\s|]*el|de )[\s|]*(?:día|dia|)[\s|]*" + identificate_day_or_month + identificate_hours + r"[\s|]*(?:hasta|al|a )[\s|]*(?:el|)[\s|]*" + identificate_day_or_month + identificate_hours + r"[\s|]*(?:del|de[\s|]*el|de)[\s|]*(?:mes|)[\s|]*(?:de|)[\s|]*(?:" + identificate_day_or_month + r"|" + months + r"|este mes|mes[\s|]*que[\s|]*viene|siguiente[\s|]*mes|mes[\s|]*siguiente|mes[\s|]*pasado|pasado[\s|]*mes|anterior[\s|]*mes|mes[\s|]*anterior)[\s|]*" + r"(?:" + identificate_years + r"|" + r")"
#Replacement in the input string by a string with built-in corrections where necessary
input_text = re.sub(identification_re_0,
lambda m: ,
input_text, re.IGNORECASE)
print(repr(input_text)) # --> output
I was trying to get that if the pattern identification_re_0 is found incomplete, that is, without the times indicated, then it completes them with "a las 00:00 am", which represents the beginning of that indicated day with that date.
Within the same input string there may be more than one occurrence of this pattern where this procedure must be performed, therefore the number of replacements in the re.sub() function has not been limited. And I have added the re.IGNORECASE flag since capital letters should not have relevance when performing time recognition within a text.
And the correct output in each of the cases should be like this.
'del dia 10 a las 10:00 am hasta el 15 a las 00:00 am de noviembre de 2020' #for the example 1
'de el 10 a las 00:00 am hasta el 15 a las 20:00 pm de noviembre del año 2020' #for the example 2
'desde el 10 a las 00:00 am hasta el 15 a las 00:00 am de noviembre del año 2020' #for the example 3
'del 10 a las 10:00 am hasta el 15 a las 20:00 pm de noviembre de 2020' #for the example 4, NOT modify
In example 1 , "a las 00:00 am" has been added to the first date (reading from left to right).
In example 2 , "a las 00:00 am" has been added to the second date.
And in example 3, "a las 00:00 am" has been added to both dates that make up the time interval.
Note that in example 4 it was not necessary to add anything, since the times associated with the dates are already indicated (following the model pattern).
you can capture the part of string which has to be replaced and then replace them as in orginal text.
In regex, (?!a\slas) will validate next words not same as a las.
sample code
import re
def replacer(string, capture_data, replaced_data):
for i in range(len(capture_data)):
string = string.replace(capture_data[i], replaced_data[i])
return string
text = 'del dia 10 a las 10:00 am hasta el 15 de noviembre de 2020'
text1 = 'de el 10 hasta el 15 a las 20:00 pm de noviembre del año 2020' # example 2
text2 = 'desde el 10 hasta el 15 de noviembre del año 2020' # example 3
text3 = 'del 10 a las 10:00 am hasta el 15 a las 20:00 pm de noviembre de 2020'
re_exp = r'[A-Za-z]+\s\d{2}\s(?!a\slas)'
capture_data = re.findall(re_exp, text3)
replaced_data = [i + "a las 00:00 am " for i in capture_data]
print(replacer(text3, capture_data, replaced_data))
>>> del 10 a las 10:00 am hasta el 15 a las 20:00 pm de noviembre de 2020

Scraping issue with id_tag

I'm trying to extract data from a website with BeautifulSoup.
I'm actually stuck with this :
"Trad. de l'anglais par < a href="/searchinternet/advanced?all_authors_id=35534&SearchAction=1">Camille Fabien < /a>"
I want to get the names of translaters but the tag uses their id.
my code is
translater = soup.find_all("a", href="/searchinternet/advanced?all_authors_id=")
I tried with a str.startswith but it doesn't work.
Can someone help me plz?
Providing your HTML is correct, static (doesn't get loaded with javascript after initial page load), this is one way to select that/those links:
from bs4 import BeautifulSoup as bs
html = '''<p>Trad. de l'anglais par Camille Fabien </p>'''
soup = bs(html, 'html.parser')
a = soup.select('a[href^="/searchinternet/advanced?all_authors_id="]')
print(a[0])
print(a[0].get_text(strip=True))
print(a[0].get('href'))
Result in terminal:
Camille Fabien
Camille Fabien
/searchinternet/advanced?all_authors_id=35534&SearchAction=1
EDIT: Who doesn't like a challenge?... Based on further comments made by OP, here is a way of obtaining titles, authors, translators and illustrator from that page - considering there can be one, or more translators/one or more illustrators:
from bs4 import BeautifulSoup as bs
import requests
import pandas as pd
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
}
url = 'https://www.gallimard.fr/searchinternet/advanced/(editor_brand_id)/1/(fserie)/FOLIO-JUNIOR+LIVRE+HEROS%3A%3AFolio+Junior+-+Un+Livre+dont+Vous+%C3%AAtes+le+H%C3%A9ros+%40+DEFIS+FANTASTIQ%3A%3AS%C3%A9rie+D%C3%A9fis+Fantastiques/(limit)/3?date%5Bfrom%5D=1980-01-01&date%5Bto%5D=1995-01-01&SearchAction=OK'
big_list = []
r = requests.get(url, headers=headers)
soup = bs(r.text, 'html.parser')
items = soup.select('div[class="results bg_white"] > table div[class="item"]')
print()
for i in items:
title = i.select_one('div[class="title"] h3')
author = i.select_one('div[class="author"] a')
history = i.select_one('p[class="collective_work_entries"]')
translators = [[y.get_text() for y in x.find_previous_siblings('a')] for x in history.contents if "Illustrations" in x]
illustrators = [[y.get_text() for y in x.find_next_siblings('a')] for x in history.contents if "Illustrations" in x]
big_list.append((title.text.strip(), author.text.strip(), ', '.join([x for y in translators for x in y]), ', '.join([x for y in illustrators for x in y])))
df = pd.DataFrame(big_list, columns = ['Title', 'Author', 'Translator(s)', 'Illustrator(s)'])
print(df)
Result in terminal:
Title
Author
Translator(s)
Illustrator(s)
0
Le Sépulcre des Ombres
Jonathan Green
Noël Chassériau
Alan Langford
1
La Légende de Zagor
Ian Livingstone
Pascale Houssin
Martin McKenna
2
Les Mages de Solani
Keith Martin
Noël Chassériau
Russ Nicholson
3
Le Siège de Sardath
Keith P. Phillips
Yannick Surcouf
Pete Knifton
4
Retour à la Montagne de Feu
Ian Livingstone
Yannick Surcouf
Martin McKenna
5
Les Mondes de l'Aleph
Peter Darvill-Evans
Yannick Surcouf
Tony Hough
6
Les Mercenaires du Levant
Paul Mason
Mona de Pracontal
Terry Oakes
7
L'Arpenteur de la Lune
Stephen Hand
Pierre de Laubier
Martin McKenna, Terry Oakes
8
La Tour de la Destruction
Keith Martin
Mona de Pracontal
Pete Knifton
9
La Légende des Guerriers Fantômes
Stephen Hand
Alexis Galmot
Martin McKenna
10
Le Repaire des Morts-Vivants
Dave Morris
Nicolas Grenier
David Gallagher
11
L'Ancienne Prophétie
Paul Mason
Mona de Pracontal
Terry Oakes
12
La Vengeance des Démons
Jim Bambra
Mona de Pracontal
Martin McKenna
13
Le Sceptre Noir
Keith Martin
Camille Fabien
David Gallagher
14
La Nuit des Mutants
Peter Darvill-Evans
Anne Collas
Alan Langford
15
L'Élu des Six Clans
Luke Sharp
Noël Chassériau
Martin Mac Kenna, Martin McKenna
16
Le Volcan de Zamarra
Luke Sharp
Olivier Meyer
David Gallagher
17
Les Sombres Cohortes
Ian Livingstone
Noël Chassériau
Nik William
18
Le Vampire du Château Noir
Keith Martin
Mona de Pracontal
Martin McKenna
19
Le Voleur d'Âmes
Keith Martin
Mona de Pracontal
Russ Nicholson
20
Le Justicier de l'Univers
Martin Allen
Mona de Pracontal
Tim Sell
21
Les Esclaves de l'Eternité
Paul Mason
Sylvie Bonnet
Bob Harvey
22
La Créature venue du Chaos
Steve Jackson
Noël Chassériau
Alan Langford
23
Les Rôdeurs de la Nuit
Graeme Davis
Nicolas Grenier
John Sibbick
24
L'Empire des Hommes-Lézards
Marc Gascoigne
Jean Lacroix
David Gallagher
25
Les Gouffres de la Cruauté
Luke Sharp
Sylvie Bonnet
Russ Nicholson
26
Les Spectres de l'Angoisse
Robin Waterfield
Mona de Pracontal
Ian Miller
27
Le Chasseur des Étoiles
Luke Sharp
Arnaud Dupin de Beyssat
Cary Mayes, Gary Mayes
28
Les Sceaux de la Destruction
Robin Waterfield
Sylvie Bonnet
Russ Nicholson
29
La Crypte du Sorcier
Ian Livingstone
Noël Chassériau
John Sibbick
30
La Forteresse du Cauchemar
Peter Darvill-Evans
Mona de Pracontal
Dave Carson
31
La Grande Menace des Robots
Steve Jackson
Danielle Plociennik
Gary Mayes
32
L'Épée du Samouraï
Mark Smith
Pascale Jusforgues
Alan Langford
33
L'Épreuve des Champions
Ian Livingstone
Alain Vaulont, Pascale Jusforgues
Brian Williams
34
Défis Sanglants sur l'Océan
Andrew Chapman
Jean Walter
Bob Harvey
35
Les Démons des Profondeurs
Steve Jackson
Noël Chassériau
Bob Harvey
36
Rendez-vous avec la M.O.R.T.
Steve Jackson
Arnaud Dupin de Beyssat
Declan Considine
37
La Planète Rebelle
Robin Waterfield
C. Degolf
Gary Mayes
38
Les Trafiquants de Kelter
Andrew Chapman
Anne Blanchet
Nik Spender
39
Le Combattant de l'Autoroute
Ian Livingstone
Alain Vaulont, Pascale Jusforgues
Kevin Bulmer
40
Le Mercenaire de l'Espace
Andrew Chapman
Jean Walthers
Geoffroy Senior
41
Le Temple de la Terreur
Ian Livingstone
Denise May
Bill Houston
42
Le Manoir de l'Enfer
Steve Jackson
43
Le Marais aux Scorpions
Steve Jackson
Camille Fabien
Duncan Smith
44
Le Talisman de la Mort
Steve Jackson
Camille Fabien
Bob Harvey
45
La Sorcière des Neiges
Ian Livingstone
Michel Zénon
Edward Crosby, Gary Ward
46
La Citadelle du Chaos
Steve Jackson
Marie-Raymond Farré
Russ Nicholson
47
La Galaxie Tragique
Steve Jackson
Camille Fabien
Peter Jones
48
La Forêt de la Malédiction
Ian Livingstone
Camille Fabien
Malcolm Barter
49
La Cité des Voleurs
Ian Livingstone
Henri Robillot
Iain McCaig
50
Le Labyrinthe de la Mort
Ian Livingstone
Patricia Marais
Iain McCaig
51
L'Île du Roi Lézard
Ian Livingstone
Fabienne Vimereu
Alan Langford
52
Le Sorcier de la Montagne de Feu
Steve Jackson
Camille Fabien
Russ Nicholson
Bear in mind this method fails for Le Manoir de l'Enfer, because word 'Illustrations' is not found in text. It's down to the OP to find a solution for that one.
BeautifulSoup documentation can be found at https://beautiful-soup-4.readthedocs.io/en/latest/index.html
Also, Pandas docs can be found here: https://pandas.pydata.org/pandas-docs/stable/index.html
from bs4 import BeautifulSoup
soup = BeautifulSoup(open("./test.html", "r"),'html.parser') #returns a list
names = []
for elem in soup:
names.append(elem.text)

Select Substring in between spaces

Please see the following reproducable example:
{'URL': {0: 'https://www.funda.nl/koop/verkocht/nijmegen/huis-41264739-st-jacobslaan-293/', 1: 'https://www.funda.nl/koop/verkocht/didam/huis-41266611-dr-ariensstraat-15/'}, 'OfferedSince': {0: '16 januari 2021', 1: '8 januari 2021'}, 'DateOfSale': {0: '18 maart 2021', 1: '14 april 2021'}, 'AskingPrice': {0: '€ 309.000 k.k.', 1: '€ 480.000 k.k.'}, 'Description': {0: "Bekijk de uitgebreide fotopresentatie en Walk Through Video online! Interesse? Vraag een bezichtiging aan per e-mail of neem telefonisch contact met ons op! In de gewilde woonwijk Hatertse Hei nabij het Radboud UMC gelegen charmant helft van dubbel woonhuis met carport, diepe zonnige tuin (gelegen op het Zuidoosten) en parkeermogelijkheid op eigen terrein. De vrijstaande houten schuur van ca. 10 m2 biedt genoeg ruimte om fietsen of een motor binnen neer te zetten. Dit karakteristieke woonhuis ligt op een royaal perceel van 276 m2 en biedt volop mogelijkheden voor uitbreiding! Deze in jaren '30 stijl gebouwde woning is door de jaren heen prima onderhouden maar dient intern gemoderniseerd te worden. De Hatertse Hei is een rustige en zeer courante buurt op circa 10 minuten fietsen van het centrum van Nijmegen waardoor alle wijk,-en stadsvoorzieningen zoals winkels en scholen en het Centraal station direct onder handbereik zijn. Wandelen, fietsen en sporten laat zich goed met stads wonen combineren door de nabijheid van goede sportfaciliteiten, het Goffertpark en de bossen van Heumensoord. Indeling: Begane Grond: Entree, hal met trapopgang en toegang tot de kelder, L-vormige woonkamer met gashaard. Vanuit de woonkamer toegang tot de dichte keuken welke voorzien is van enkele apparatuur. Via de hal toegang naar de badkamer en de op het Zuidoosten gelegen achtertuin. De badkamer is voorzien van een inloopdouche, vaste wastafel en toilet. 1e Verdieping: Overloop, 3 slaapkamers van goed formaat. De slaapkamer aan de voorzijde van de woning is voorzien van een inbouwkast. Bijzonderheden - Bouwjaar 1924; - Perceeloppervlakte 276 m2; - Woonoppervlakte 74 m2; - Inhoud 280 m3; - Meetrapport Nen 2580 aanwezig; - Intergas cv ketel uit 2009; - Energielabel G. Wijkinformatie: De Hatertse Hei is een centraal in Nijmegen gelegen kindvriendelijke woonwijk met veelal vooroorlogse woningen en woningen uit de jaren '50 en '60. Deze geliefde wijk is grofweg gelegen tussen de St. Annastraat ter hoogte van het UMC Radboud en de Hazenkamp. De wijk ligt op loopafstand van de Radboud Universiteit en het UMC Radboud en is op slechts 10 minuten fietsen gelegen van het centrum. Wijkvoorzieningen zoals scholen en winkels zijn ruimschoots aanwezig.", 1: 'Bijzonder fraai en royaal wonen in de gemeente Montferland? Het kan! Op uitstekende locatie tegenover plantsoen in ruim opgezette woonomgeving in één van de meest geliefde woonwijken aan de rand van Didam gelegen riante vrijstaande woning met vrijstaande stenen garage/ berging voorzien van zolder, carport geschikt voor stalling van camper en goed omsloten tuin met veel privacy. De speels aangelegde achtertuin is gesitueerd op het zonnige Zuiden en voorzien van een royaal zonneterras met diverse borders; u kunt ook binnenshuis optimaal van de tuin genieten vanwege de grote glazen pui in de woonkamer. Het woonhuis beschikt voorts over een royale kantoorruimte (eventueel in te richten als slaapkamer) (voorheen 2 kamers; in 1980 getransformeerd tot 1 grote kamer van circa 5.65 m x 3.35 m) een riante woonkamer (circa 50 m2) en 5 slaapkamers alsmede 2 badkamers op de de eerste verdieping, waardoor de woning voor meerdere doelgroepen geschikt is waaronder grote gezinnen. Bovendien uitermate geschikt voor de combinatie wonen-werken aan huis. Er is ruimschoots voldoende parkeergelegenheid op eigen terrein. Dit vrijstaand woonhuis is geheel op traditionele wijze gebouwd in 1974, meet een comfortabele inhoud van 770 m³ en heeft een zeer royale woonoppervlakte 200 m². Het geheel staat gesitueerd op een perceel van maar liefst 664 m² eigen grond. Deze woning is gunstig gelegen in een rustige woonomgeving nabij het centrum van Didam. Didam beschikt over veel eigen voorzieningen zoals een uitgebreid scala aan winkels, een eigen trein- en busstation, basisscholen en voortgezet onderwijs. Tevens zijn er diverse sportaccommodaties zoals tennis- en voetbalvelden en een fitnesscentra. De recreatie / natuurgebieden “de Nevelhorst”, “t Baerlebos” en de Montferlandse bossen, met haar vele wandel-, fiets- en ruiterpaden, bevinden zich op korte afstand. Het object is centraal gelegen in de stedendriehoek Arnhem-Doetinchem-Nijmegen, de ontsluitingswegen A12 (Arnhem), A18 (Doetinchem) en de A3 (Duitsland) bereikt u binnen enkele autominuten. INDELING Begane grond: Thuiskomen via royaal overdekte entree, zeer royale statige hal met daarboven een vide, meterkast v.v. glasvezelaansluiting, zeer royale L vormige living welke onder te verdelen is tot bijvoorbeeld eet- en zitkamer, v.v. haardpartij en riante glazen pui (deels schuifpui) waardoor optimale lichtinval en uitstekend zicht op de tuin. Dichte keuken voorzien van inbouwkeuken met RVS kooktoestel (heteluchtoven en 5-pits gas koken) en RVS afzuigschouw. Grote werkkamer annex 6e slaapkamer welke eventueel te splitsen is tot 2 kamers. Eerste verdieping: Overloop, vide, 5 goed bemeten slaapkamers waarbij 2 slaapkamers toegang bieden tot het balkon aan de westzijde, badkamer voorzien van ligbad, 2e toilet en 2 wastafels en tweede badkamer welke is voorzien van douche en wastafel. Tweede verdieping: Royale zolder te bereiken via vlizotrap. Bijzonderheden: Bouwjaar 1974 Perceelgrootte 664 m2 Woonoppervlakte 200 m2 Externe bergruime 26 m2; overige inpandige ruimte 19 m2 en gebouw gebonden buitenruimte 5 m2 Inhoud ca. 770 m2 volgens NEN 2580 Meetrapport Aanvullende informatie: Energielabel D HR combiketel 2017 Buitenschilderwerk 2016 Gedeeltelijk kunststof kozijnen met dubbel glas. Rustig gelegen in een ruim opgezette woonomgeving aan de rand van Didam. Het centrum van Didam ligt op loopafstand. Er zijn uitstekende autoverbindingen en openbaar vervoerverbindingen naar o.a. Arnhem, Duitsland, Doetinchem en Zevenaar. Didam is een plaats met ongeveer 16.500 inwoners. Het maakt onderdeel uit van de gemeente Montferland. De gemeente Montferland ligt in Oost Nederland, direct tegen de Duitse grens. ’s-Heerenberg en Didam zijn de levendige centra van de gemeente Montferland, maar ook de kleine pittoreske dorpjes zijn zeker een bezoek waard. Grotere plaatsen in de omgeving zijn Arnhem en Doetinchem. De gemeente Montferland kenmerkt zich in een afwisselend landschap, mooie bossen en beschikt daarnaast over alle faciliteiten om lekker tot rust te komen. Naast de natuur kunt u ook qua cultuur en historie uw hart ophalen in Montferland en omgeving. Niet voor niets is de slogan van de gemeente “Groen met karakter!”. Interesse in dit huis? Schakel direct uw eigen NVM-aankoopmakelaar in. Uw NVM-aankoopmakelaar komt op voor uw belang en bespaart u tijd en zorgen. Adressen van collega NVM-aankoopmakelaars vindt u op Funda.'}, 'Postcode': {0: '6533 VD', 1: '6941 CJ'}, 'LivingArea': {0: '74 m²', 1: '200 m²'}, 'PlotArea': {0: '276 m²', 1: '664 m²'}, 'Rooms': {0: 4, 1: 7}, 'Bedrooms': {0: '4 kamers (3 slaapkamers)', 1: '7 kamers (6 slaapkamers)'}, 'Bathrooms': {0: '1 badkamer', 1: '2 badkamers en 1 apart toilet'}, 'EnergyLabel': {0: 'G', 1: 'D'}, 'BuildYear': {0: '1924', 1: '1974'}, 'TypeOfHouse': {0: 'Eengezinswoning, 2-onder-1-kapwoning', 1: 'Eengezinswoning, vrijstaande woning'}, 'Garden': {0: 'Achtertuin, voortuin en zijtuin', 1: 'Tuin rondom'}, 'Garden-yes-no': {0: 'Yes', 1: 'Yes'}}
I would like to get for the AskingPrice only the number.
So for € 309.000 k.k. I would only like to have 309.000 . How do I do this? Furthermore, I would like to have this for all the rows in the dataFrame, Can i just apply a for loop?
Thanks in advance : )
Try this:
df['AskingPrice'] = df['AskingPrice'].str.split(' ').str[1].astype(float)
Output:
>>> df
URL OfferedSince DateOfSale AskingPrice ... BuildYear TypeOfHouse Garden Garden-yes-no
0 https://www.funda.nl/koop/verkocht/nijmegen/hu... 16 januari 2021 18 maart 2021 309.0 ... 1924 Eengezinswoning, 2-onder-1-kapwoning Achtertuin, voortuin en zijtuin Yes
1 https://www.funda.nl/koop/verkocht/didam/huis-... 8 januari 2021 14 april 2021 480.0 ... 1974 Eengezinswoning, vrijstaande woning Tuin rondom Yes
[2 rows x 16 columns]
Try str.extract
df['AskingPrice'] = df['AskingPrice'].str.extract(r'\s+([\d\.]*)\s', expand=False)
print(df['AskingPrice'])
# Output:
0 309.000
1 480.000
Name: AskingPrice, dtype: object
You can append .astype(float) if you want to convert it to float.

Data formatting in Python

I want to know if there is a possibility to modify these dates (they are in PT-BR), I want to put them in numerical form in EN or PT-BR.
Início Fim
0 15 de março de 1985 14 de fevereiro de 1986
1 14 de fevereiro de 1986 23 de novembro de 1987
2 23 de novembro de 1987 15 de janeiro de 1989
3 16 de janeiro de 1989 14 de março de 1990
4 15 de março de 1990 23 de janeiro de 1992
We can setlocale LC_TIME to pt_PT then to_datetime will work as expected with a format string:
import locale
import pandas as pd
locale.setlocale(locale.LC_TIME, 'pt_PT')
df = pd.DataFrame({
'Início': ['15 de março de 1985', '14 de fevereiro de 1986',
'23 de novembro de 1987', '16 de janeiro de 1989',
'15 de março de 1990'],
'Fim': ['14 de fevereiro de 1986', '23 de novembro de 1987',
'15 de janeiro de 1989', '14 de março de 1990',
'23 de janeiro de 1992']
})
cols = ['Início', 'Fim']
df[cols] = df[cols].apply(pd.to_datetime, format='%d de %B de %Y')
df:
Início Fim
0 1985-03-15 1986-02-14
1 1986-02-14 1987-11-23
2 1987-11-23 1989-01-15
3 1989-01-16 1990-03-14
4 1990-03-15 1992-01-23
Split the string inside each cell by " de ".
Replace the 2nd element with the corresponding number (I suggest using a dictionary for this).
Join the list into a string. I suggest using str.join, but string concatenation or formatted strings work too.
Let's use an example.
date = "23 de novembro de 1987"
dates = date.split(" de ") # ['23', 'novembro', '1987']
dates[1] = "11" # ['23', '11', '1987']
numerical_date = '/'.join(dates) # "23/11/1987"

Removing entire row if there are repetitive values in specific columns

I Have read a CSV file (that have name and addresses of customers) and assign the data into DataFrame table.
Description of the csv file (or the DataFrame table)
DataFrame contains several rows and 7 columns
Database example
Client_id Client_Name Address1 Address3 Post_Code City_Name Full_Address
C0000001 A 10000009 37 RUE DE LA GARE L-7535 MERSCH 37 RUE DE LA GARE,L-7535, MERSCH
C0000001 A 10000009 37 RUE DE LA GARE L-7535 MERSCH 37 RUE DE LA GARE,L-7535, MERSCH
C0000001 A 10000009 37 RUE DE LA GARE L-7535 MERSCH 37 RUE DE LA GARE,L-7535, MERSCH
C0000002 B 10001998 RUE EDWARD STEICHEN L-1855 LUXEMBOURG RUE EDWARD STEICHEN,L-1855,LUXEMBOURG
C0000002 B 10001998 RUE EDWARD STEICHEN L-1855 LUXEMBOURG RUE EDWARD STEICHEN,L-1855,LUXEMBOURG
C0000002 B 10001998 RUE EDWARD STEICHEN L-1855 LUXEMBOURG RUE EDWARD STEICHEN,L-1855,LUXEMBOURG
C0000003 C 11000051 9 RUE DU BRILL L-3898 FOETZ 9 RUE DU BRILL,L-3898 ,FOETZ
C0000003 C 11000051 9 RUE DU BRILL L-3898 FOETZ 9 RUE DU BRILL,L-3898 ,FOETZ
C0000003 C 11000051 9 RUE DU BRILL L-3898 FOETZ 9 RUE DU BRILL,L-3898 ,FOETZ
C0000004 D 10000009 37 RUE DE LA GARE L-7535 MERSCH 37 RUE DE LA GARE,L-7535, MERSCH
C0000005 E 10001998 RUE EDWARD STEICHEN L-1855 LUXEMBOURG RUE EDWARD STEICHEN,L-1855,LUXEMBOURG
So far I have written this code to generate the aformentioned table :
The code is
import pandas as pd
import glob
Excel_file = 'Address.xlsx'
Address_Info = pd.read_excel(Excel_file)
# rename the columns name
Address_Info.columns = ['Client_ID', 'Client_Name','Address_ID','Street_Name','Post_Code','City_Name','Country']
# extract specfic columns into a new dataframe
Bin_Address= Address_Info[['Client_Name','Address_ID','Street_Name','Post_Code','City_Name','Country']].copy()
# Clean existing whitespace from the ends of the strings
Bin_Address= Bin_Address.apply(lambda x: x.str.strip(), axis=1) # ← added
# Adding a new column called (Full_Address) that concatenate address columns into one
# for example Karlaplan 13,115 20,STOCKHOLM,Stockholms län, Sweden
Bin_Address['Full_Address'] = Bin_Address[Bin_Address.columns[1:]].apply(lambda x: ','.join(x.dropna().astype(str)), axis=1)
Bin_Address['Full_Address']=Bin_Address[['Full_Address']].copy()
Bin_Address['latitude'] = 'None'
Bin_Address['longitude'] = 'None'
# Remove repetitive addresses
#Temp = list( dict.fromkeys(Bin_Address.Full_Address) )
# Remove repetitive values ( I do beleive the modification should be here)
Temp = list( dict.fromkeys(Address_Info.Client_ID) )
I am looking to remove the entire row if there are repetitive values in the Client id, Client name , and Full_Address columns, so far code doesnt show any error but at the same time, I havnt got the expected out ( i do beleive the modification would be in the last line of the attached code)
The expected output is
Client_id Client_Name Address1 Address3 Post_Code City_Name Full_Address
C0000001 A 10000009 37 RUE DE LA GARE L-7535 MERSCH 37 RUE DE LA GARE,L-7535, MERSCH
C0000002 B 10001998 RUE EDWARD STEICHEN L-1855 LUXEMBOURG RUE EDWARD STEICHEN,L-1855,LUXEMBOURG
C0000003 C 11000051 9 RUE DU BRILL L-3898 FOETZ 9 RUE DU BRILL,L-3898 ,FOETZ
C0000004 D 10000009 37 RUE DE LA GARE L-7535 MERSCH 37 RUE DE LA GARE,L-7535, MERSCH
C0000005 E 10001998 RUE EDWARD STEICHEN L-1855 LUXEMBOURG RUE EDWARD STEICHEN,L-1855,LUXEMBOURG
You can use built in method called dorp_duplicates() from pandas. Also there is lot of options out of the box you can apply.
<your_dataframe>.drop_duplicates(subset=["Client_id", "Client_name", "Full_Address"])
You also have options for when it is duplicate, if you want to keep the first value or last value.
<your_dataframe>.drop_duplicates(subset=["Client_id", "Client_name", "Full_Address"], keep="first") # "first" or "last"
By default it will always keep the first value.
Try:
df = df.drop_duplicates(['Client id', 'Client name', 'Full_Address'])

Categories

Resources