Python Lesson 33: Stopwords (NLP pt.2)

Hello everybody,

Michael here, and today’s post will be on stopwords in Python NLP-part 2 in my NLP series.

What are stopwords? Simply put, stopwords are words you want to ignore when tokenizing a string. Oftentimes, stopwords are common English words like “a”, “the”, and “is” that are so commonly used in English that they don’t add much meaning in text.

  • Stopwords can be found for any language, but for this series of NLP lessons, I’ll focus on English words.

Now that I’ve explained the basics of stopwords, let’s see them in action:

import nltk
nltk.download('punkt')
nltk.download('stopwords')
from nltk.corpus import stopwords

test = input('Please type in a string: ')
testWords = nltk.word_tokenize(test)

stopwordsList = set(stopwords.words('english'))

filteredList = []

for t in testWords:
    if t.casefold() not in stopwordsList:
        filteredList.append(t)

print(filteredList)

Please type in a string: The puppies and the kitties played in their playpen on the hot summer afternoon.
['puppies', 'kitties', 'played', 'playpen', 'hot', 'summer', 'afternoon', '.']

To utilize NLTK’s stopwords module, you’ll need to run the nltk.download(stopwords) command and import the stopwords module from the nltk.corpus package.

  • Yes, you’ll still need to download the punkt module, as it will enable easy tokenization, which is important to have when working with stopwords.

To store the list of tokens in the string you input, create a testWords variable that stores the output of the nltk.word_tokenize function. To get a list of NLTK’s English stopwords, use the line of code set(stopwords.words('english'))-this line of code creates a set from the list of NLTK’s English stopwords. Recall that sets are like lists, except without duplicate elements.

To gather a list of stopwords in the input string, you’d need to first create an empty list-filteredList in this case-that you’ll need to filter the stopwords out of the list of tokens (testWords in this case). To remove the stopwords, you’ll need to iterate through the list of tokens (again, testWords in this case), check if each token is in the list of stopwords and if not, add the token to the empty list you created earlier (filteredList in this case).

As you can see in the example above, the input string I used has 15 tokens (the punctuation at the end of the sentence counts as a token). After filtering out the stopwords, the resulting list only contains 8 tokens, as 7 tokens have been filtered out-The and the in their on the. Yes, even though I am iterating though a UNIQUE list of stopwords, the loop I am running will check for all instances of a stopword and exclude them from the filtered list (after all, there were three instances of the word “the” in the input string).

Ever want to see all of the words included in NLTK’s English stopwords list? Run the command print(stopwords.words('english') and you’ll see all the stopwords NLTK uses in English:

['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]

In total, NLTK has 179 stopwords in English, which consist of common English pronouns (I, my, you), commonly used English contracations (don’t, isn’t), conjungations of common English verbs (such as be and have), and surprisingly, contractions that you don’t hear most people use nowadays (be honest, when was the last time you heard someone use a word like shan’t or mightn’t).

  • Of course, you can always append words to NLTK’s stopwords list as you see fit, but when working with stopwords in English (or any language), I’d suggest sticking with the default stopwords list.

Now, I know I mentioned that I’ll mostly be working with English throughout my NLP lessons, but let’s explore stopwords in other languages. For this example, I’ll use the same code and same input string I used in the previous example, except this time use Spanish:

Please type in a string: Los cachorros y los gatitos jugaban en su corralito en la calurosa tarde de verano.
['cachorros', 'gatitos', 'jugaban', 'corralito', 'calurosa', 'tarde', 'verano', '.']

So, the Spanish-translated version of my previous example has 16 tokens, 8 of which appear on the filtered list. Thus, there were 8 stopwords that were removed from the testWords list.

Want to see the Spanish list of stopwords? Run the command print(stopwords.words('spanish') and take a look:

['de', 'la', 'que', 'el', 'en', 'y', 'a', 'los', 'del', 'se', 'las', 'por', 'un', 'para', 'con', 'no', 'una', 'su', 'al', 'lo', 'como', 'más', 'pero', 'sus', 'le', 'ya', 'o', 'este', 'sí', 'porque', 'esta', 'entre', 'cuando', 'muy', 'sin', 'sobre', 'también', 'me', 'hasta', 'hay', 'donde', 'quien', 'desde', 'todo', 'nos', 'durante', 'todos', 'uno', 'les', 'ni', 'contra', 'otros', 'ese', 'eso', 'ante', 'ellos', 'e', 'esto', 'mí', 'antes', 'algunos', 'qué', 'unos', 'yo', 'otro', 'otras', 'otra', 'él', 'tanto', 'esa', 'estos', 'mucho', 'quienes', 'nada', 'muchos', 'cual', 'poco', 'ella', 'estar', 'estas', 'algunas', 'algo', 'nosotros', 'mi', 'mis', 'tú', 'te', 'ti', 'tu', 'tus', 'ellas', 'nosotras', 'vosotros', 'vosotras', 'os', 'mío', 'mía', 'míos', 'mías', 'tuyo', 'tuya', 'tuyos', 'tuyas', 'suyo', 'suya', 'suyos', 'suyas', 'nuestro', 'nuestra', 'nuestros', 'nuestras', 'vuestro', 'vuestra', 'vuestros', 'vuestras', 'esos', 'esas', 'estoy', 'estás', 'está', 'estamos', 'estáis', 'están', 'esté', 'estés', 'estemos', 'estéis', 'estén', 'estaré', 'estarás', 'estará', 'estaremos', 'estaréis', 'estarán', 'estaría', 'estarías', 'estaríamos', 'estaríais', 'estarían', 'estaba', 'estabas', 'estábamos', 'estabais', 'estaban', 'estuve', 'estuviste', 'estuvo', 'estuvimos', 'estuvisteis', 'estuvieron', 'estuviera', 'estuvieras', 'estuviéramos', 'estuvierais', 'estuvieran', 'estuviese', 'estuvieses', 'estuviésemos', 'estuvieseis', 'estuviesen', 'estando', 'estado', 'estada', 'estados', 'estadas', 'estad', 'he', 'has', 'ha', 'hemos', 'habéis', 'han', 'haya', 'hayas', 'hayamos', 'hayáis', 'hayan', 'habré', 'habrás', 'habrá', 'habremos', 'habréis', 'habrán', 'habría', 'habrías', 'habríamos', 'habríais', 'habrían', 'había', 'habías', 'habíamos', 'habíais', 'habían', 'hube', 'hubiste', 'hubo', 'hubimos', 'hubisteis', 'hubieron', 'hubiera', 'hubieras', 'hubiéramos', 'hubierais', 'hubieran', 'hubiese', 'hubieses', 'hubiésemos', 'hubieseis', 'hubiesen', 'habiendo', 'habido', 'habida', 'habidos', 'habidas', 'soy', 'eres', 'es', 'somos', 'sois', 'son', 'sea', 'seas', 'seamos', 'seáis', 'sean', 'seré', 'serás', 'será', 'seremos', 'seréis', 'serán', 'sería', 'serías', 'seríamos', 'seríais', 'serían', 'era', 'eras', 'éramos', 'erais', 'eran', 'fui', 'fuiste', 'fue', 'fuimos', 'fuisteis', 'fueron', 'fuera', 'fueras', 'fuéramos', 'fuerais', 'fueran', 'fuese', 'fueses', 'fuésemos', 'fueseis', 'fuesen', 'sintiendo', 'sentido', 'sentida', 'sentidos', 'sentidas', 'siente', 'sentid', 'tengo', 'tienes', 'tiene', 'tenemos', 'tenéis', 'tienen', 'tenga', 'tengas', 'tengamos', 'tengáis', 'tengan', 'tendré', 'tendrás', 'tendrá', 'tendremos', 'tendréis', 'tendrán', 'tendría', 'tendrías', 'tendríamos', 'tendríais', 'tendrían', 'tenía', 'tenías', 'teníamos', 'teníais', 'tenían', 'tuve', 'tuviste', 'tuvo', 'tuvimos', 'tuvisteis', 'tuvieron', 'tuviera', 'tuvieras', 'tuviéramos', 'tuvierais', 'tuvieran', 'tuviese', 'tuvieses', 'tuviésemos', 'tuvieseis', 'tuviesen', 'teniendo', 'tenido', 'tenida', 'tenidos', 'tenidas', 'tened']

In comparison to the English stopwords list, the Spanish list has 313 stopwords. However, both the English and Spanish lists have the same type of elements, such as conjugations of commonly used verbs (such as ser and estar), common pronouns and prepositions (yo, tu, para, contra), among other things. What you don’t see much of in the Spanish stopwords list are contractions, and that’s because there are only two knwon contractions in Spanish (al and del-both of which are on this list) while English has plenty of contractions.

Now, one cool thing about working with stopwords (and NLP in general) is that you can play around with several foreign languages. Run the command print(stopwords.fileids()) to see all the languages you can play with when working with stopwords:

['arabic', 'azerbaijani', 'bengali', 'danish', 'dutch', 'english', 'finnish', 'french', 'german', 'greek', 'hungarian', 'indonesian', 'italian', 'kazakh', 'nepali', 'norwegian', 'portuguese', 'romanian', 'russian', 'slovene', 'spanish', 'swedish', 'tajik', 'turkish']

In total, you can use 24 languages when working with stopwords-from common languages like English, Spanish and French to more interesting options like Kazakh and Turkish. Interestingly, I don’t see an option to use Mandarin on here, as it’s a commonly spoken language worldwide.

Thank you,

Michael

It’s Our Fourth Anniversary Everybody!!!

Hello readers,

Michael here, and today I thought I’d celebrate the blog’s fourth anniversary (yes, I’ve been active for that long) to introduce more exciting updates to my blog (and no, there won’t be a third home). Yes, I’m still keeping my tradition of anniversary posts every June 13.

If you’ve been reading my WordPress site throughout the years, you’ll notice that not much has changed. From the blog’s name, layout, and content, not much has changed at all-after all, I’ve strived (and will continue to strive) to give you all great programming content. Hey, if it ain’t broke, don’t fix it.

But as the years have gone by, I’ve realized that this little blog of mine could use a little revamping every now and then-and to be honest, this blog is looong overdue for a little facelift.

First off, let’s start with the About Me page. Hoo boy, this may have worked when I launched this blog in 2018, but it looks awfully dated now. After all, I’m no longer a 22-year-old recent college graduate but now a 26-year-old working professional who now has had almost three years of programming job experience under his belt (when I launched this blog, I had no programming job experience, just some coding knowledge from courses I took in my last year of undergrad). Plus, I’ve been out of school for four years now-I started this blog about a month and a half after college graduation.

Now, after a little tweaking, let’s see the new About Me page:

OK, so I couldn’t capture the whole about me page in a single screenshot, but wouldn’t you say this looks much better. I describe myself and give a little more background as to why I pursued a career in coding so that you all can know why I do what I do. I also included a link to my Medium account-as many of you know, I started publishing my blogs to Medium as well as WordPress beginning in October 2021.

I also include a picture of myself, just so you-the readers-know what I look like.

  • Also, for those who may be wondering, I took this picture in June 2021 at Radnor Lake State Park in Nashville, TN. Perfect outdoor area to visit if you’re ever in Nashville.

Now, the next major update I made is post-tagging. As you readers likely have noticed, I tend to jump back and forth between programming tools a lot in my posts (e.g. in 2018, I jumped from a series of R lessons to a series of MySQL lessons and back to another series of R lessons). The reason I do this is because I like to cover a variety of programming tools to keep this blog interesting-after all, I’ve covered SEVEN different programming tools (GitHub, Python, Java, MySQL, R, HTML, and CSS) over the course of this blog’s four-year run. Since I’ve covered so many different programming tools, I know it can get messy if you’re looking for lessons pertaining to a certain tool (such as R). That’s why I’m going back and tagging all 126 of my posts (including this post). Take a look at my first R lesson from June 25, 2018:

Notice something different on the bottom? If you’ve visited my blog, you’ll notice that I didn’t have tags on my posts up until now. In this post, I just have a single tag-R-which if you click on it, you’ll see all the R posts I’ve written on this blog (well, all the R posts I’ve tagged so far):

Programming tools like R and MySQL aren’t the only things to get their own tags. Let’s say you wanted to find posts that use music-related datasets. Well, click on any post that has a music tag and watch what happens:

In this example, after I clicked on a post with a music tag, I can see all my posts that have a music tag-most of which are also MySQL lessons. For those that have read my blog for a long time, you’ll likely remember that I utilized a dataset of American music from 2000-2018 when I published my MySQL lesson series in the summer and fall of 2018.

Also, even though this is not an update, I just wanted to remind you all that, if you ever wanted to reach out to me directly, I’ve had a handy-dandy contact form on my blog since Day 1:

Hey, it’s simple, but it works. Plus, anything you post on this form will go to an e-mail account I actually check, not a throwaway account. I’d love to answer some of your coding/programming questions.

Also, last but not least, the biggest update I have for you all. You ready?

I’m changing the name of the blog! Yes, when I first created this blog, I settled on the name Michael’s Analytics Blog because, after all, my name is Michael and I was going to share solely data analytics lessons with you all (I was in the midst of a marathon of a post-college job hunt in data analytics when I launched this blog). However, throughout the years, my blog’s focus has certainly broadened from just data analytics to more programming tools such as Python, web development (with HTML and CSS) and even GitHub (recall my celebratory 100th post A Very Special 100th Post: The Basics of Git & GitHub).

So without further ado, here’s my new blog name:

Yes, this blog will now be known as Michael’s Programming Bytes. I also now have a tagline-Byte sized programming classes for all coding learners.

Honestly, with the direction the blog has taken over the last several years, I thought it was fitting to retire the Michael’s Analytics Blog name (not that there was anything wrong with it) and introduce the Michael’s Programming Bytes name. How did I land on this name? Well, think about this, dear readers. Over the last four years, I’ve given you all “bytes” of programming knowledge in seven different programming tools with each post. Plus, bytes are the smallest units of computer memory storage, and this is a programming blog after all, so I thought the name fit well.

As I just mentioned, I also have a blog tagline now-Byte sized programming classes for all coding learners. I am giving you all “byte”-sized programming “classes” with each post (hey, two programming puns in one).

  • Yes, I wanted to go all-in on the programming wordplay with the new blog name & tagline. I think you coders will get a kick out of it. Still keeping the red border on my blog-red is my favorite color after all.
  • Now that I have a new blog name, I’ll change the blog domain as well. Will keep you posted on that.

Thanks for reading these last four years! Here’s to many many more years of providing great programming content for you all.

Michael