## 3 Text Preprocessing and Exploratory NLP Techniques  
To create the classification models with the database descriptions, it is important that the text be as homogeneous as possible. Text processing was performed in a series of steps and algorithms described in Figure 9 that will be explained one by one below, which aim to reduce ambiguity without losing important information. At the beginning of the algorithm, all the data were imported to be used in the preliminary analysis through the CSV module [23] and by means of a dictionary that uses the description number as a key and contains attributes, as seen in Figure 10.  
Next, we needed to clean the data. Two functions with two different modules were used to perform this task. The first one was bs4 from BeautifulSoup [24] which removed html tags that may be in the descriptions. Figure 8: Complaints reported by bystanders over the years. Figure 10: Data structure of one dictionary element coming from the CSV file. Figure 9: Workflow diagram of the harassment classification pipeline. The second module was Contractions [25] to separate possible contractions from the text and treat them as two words. This process had the expected effect and managed to remove even the most complicated contractions such as \"gonna\" and \"wanna\"; however, it did not deal with the genitive ('s). To tokenize the text, the wordtokenize module of the nltk [26] library was used. Having previously eliminated the contractions avoids the situation where the tokenization separates text according to the apostrophes, instead taking into account the complete words, except for the's used in English, passing them to the normalization process, which aims to make all the tokens equal and easy to process. The first step was to convert the words to lowercase so that, for example, \"HOLA\" and \"hola\" are not considered two different words. The second step consisted of eliminating the genitive ('s) since it was found that it was separated during tokenization and generated errors during processing if it was not eliminated. The third one eliminated punctuation and other foreign characters that may have remained after tokenization; however, it kept accents and letters from other languages in case the processing was conducted in another language. Figure 11 shows an example of the text after processing. Another issue was language detection. During the reading process of the descriptions, it was found that they existed in several different languages; therefore, it was imperative to know the language of each one in order to be able to treat them. The most common languages and therefore the ones detected were: English, Spanish, French, Italian and German; the rest of the descriptions were saved as \"other languages\". To perform this detection, we made use of the stop words of each dictionary which, as previously mentioned, are the most frequent words in a language. For each language, the number of stop words in the text was counted, and the language in which this number was the highest was chosen. To deal with \"other languages\", a minimum count of stop words was established, if they did not reach the \"other\" category. This minimum started as 5, but later, it was realized that it did not work for long texts since words such as \"a\" occur in all languages. Therefore, we ended up filtering according to size and establishing that at least 10% of the words had to be stop words to belong to a language. This process still presented some problems with similar languages such as Spanish and Portuguese. If we wanted more precision, we could solve it by comparing the whole dictionary instead of the stop words; however, this would be a very slow process and would consume a lot of resources. For this paper, only the English descriptions were used, which are the most numerous in the database; the rest of the descriptions were stored for future analysis. As mentioned before, sometimes, there are some languages that are mislabeled due to stop words; this happens in the case of English.