<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>computer science on C'est la Z</title><link>https://cestlaz.github.io/cestlaz-old-hugo.github.io/tags/computer-science/</link><description>C'est la Z (computer science)</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 15 Nov 2019 16:18:51 -0400</lastBuildDate><atom:link href="https://cestlaz.github.io/cestlaz-old-hugo.github.io/tags/computer-science/rss.xml" rel="self" type="application/rss"/><item><title>Working with texts part 1 - cleaning the data</title><link>https://cestlaz.github.io/cestlaz-old-hugo.github.io/post/cleaning-textx/</link><pubDate>Fri, 15 Nov 2019 16:18:51 -0400</pubDate><guid>https://cestlaz.github.io/cestlaz-old-hugo.github.io/post/cleaning-textx/</guid><description>&lt;p>
I run periodic professional development sessions here in New York with
my partner in crime JonAlf Dyrland-Weaver. I call them PD for &amp;#34;APCS-A,
similar or beyond&amp;#34; and they&amp;#39;re designed to fill a professional
development gap. We try to run them once a month but it&amp;#39;s a little
less frequent than that.&lt;/p>
&lt;p>
The NYCDOE has taken on the monster task of CS for all and since
they&amp;#39;re trying to get to everyone they have to run a bazillion
sessions but all at an introductory level. Beyond that, most PD is
tied to a curriculum, program, or product. We decided to run sessions
for teachers who are ready for more both pedagogically and content
wise while not affiliating with any specific provider. We&amp;#39;re just
about the CS and the teaching of CS.&lt;/p>
&lt;p>
Yesterday we had our first session of the year and the content topic
was text processing. Along the way, we used it as an opportunity to
highlight subgoal labeling as a teaching technique.&lt;/p>
&lt;p>
There&amp;#39;s a lot you can do in both CS0 and CS1 with text and document
processing. By the end of yesterday&amp;#39;s session we had discussed a bunch
of possibilities based on the text processing technique known as a
&amp;#34;bag of words&amp;#34; which basically takes a text and just considers all the
words it contains. What are the words and how many times does each
word occurs. No consideration of order, grammar, or anything else. Just
words and counts. We also talked a bit about more advanced possibilities
like playing with an inverted index. I&amp;#39;ll talk about both of those in
a future post. &lt;/p>
&lt;p>
For today, let&amp;#39;s talk about what we have to do before we even begin -
preprocessing the data.&lt;/p>
&lt;p>
We grabbed a bunch of texts from &lt;a href="https://www.gutenberg.org/">Project Gutenberg&lt;/a>. Specifically, &amp;#34;Moby
Dick&amp;#34;, a translation of my favorite play &amp;#34;Cyrano de Bergerac&amp;#34; and the
Book of Psalms from the Bible. I also made a copy of the first chapter
of &amp;#34;Moby Dick&amp;#34; so we had a shorter corpus to play with and typed up
the first scene of &amp;#34;Macbeth&amp;#34; - all thirteen lines of it.&lt;/p>
&lt;p>
It&amp;#39;s easy enough to read in the data in a language like Python:&lt;/p>
&lt;p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>f &lt;span style="color:#f92672">=&lt;/span> open(&lt;span style="color:#e6db74">&amp;#34;cyrano.txt&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>raw_data &lt;span style="color:#f92672">=&lt;/span> f&lt;span style="color:#f92672">.&lt;/span>read()&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;p>
but if you&amp;#39;re using a bag of words you&amp;#39;ve got to do some cleaning.&lt;/p>
&lt;p>
To start, all Project Gutenberg texts contain a whole bunch of front
and back matter with lots of words. If you don&amp;#39;t get rid of them
you&amp;#39;ll get extra words in your bag. I forgot to do this and was a bit
surprised to see phrases like &amp;#34;Pay a trademark license&amp;#34; in the Book of
Psalms.&lt;/p>
&lt;p>
It&amp;#39;s easy enough to just cut the tops and bottoms of each file off
with an editor and that&amp;#39;s when we can read our data into our program
and the fun begins.&lt;/p>
&lt;p>
First we had to turn everything into lower case;&lt;/p>
&lt;p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>lower_data &lt;span style="color:#f92672">=&lt;/span> raw_data&lt;span style="color:#f92672">.&lt;/span>lower()&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;p>
and then the big part - we want to get rid of all the punctuation. We
first tried something like this:&lt;/p>
&lt;p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>stuff_to_remove &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;.:;&amp;#39;0123456789&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2&lt;/span>&lt;span>cleaned_letters &lt;span style="color:#f92672">=&lt;/span> [x &lt;span style="color:#66d9ef">for&lt;/span> x &lt;span style="color:#f92672">in&lt;/span> lower_data &lt;span style="color:#66d9ef">if&lt;/span> x &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> stuff_to_remove]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3&lt;/span>&lt;span>cleaned_string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>join(cleaned_letters)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;p>
The second line is a list comprehension. It iterates through each
letter in lower_data and copies it into the resultant list only if the
letter is not in our stuff_to_remove list.&lt;/p>
&lt;p>
For example, if we had &lt;code>lower_data = &amp;#34;abc123def g&amp;#34;&lt;/code> we&amp;#39;d get a result
of &lt;code>[&amp;#34;a&amp;#34;,&amp;#34;b&amp;#34;,&amp;#34;c&amp;#34;,&amp;#34;d&amp;#34;,&amp;#34;e&amp;#34;,&amp;#34;f&amp;#34;,&amp;#34; &amp;#34;,&amp;#34;g&amp;#34;]&lt;/code>. We then use the join in line 3
to turn it back into a string &lt;code>&amp;#34;abcdef g&amp;#34;&lt;/code>.&lt;/p>
&lt;p>
This worked pretty well but we found that there were problems. There
were characters that we didn&amp;#39;t account for like long dashes that
connected words and we didn&amp;#39;t have an easy way to put them in our
removal string.&lt;/p>
&lt;p>
This led to take 2. Instead of deciding what to throw away, let&amp;#39;s
decide what to keep;&lt;/p>
&lt;p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>stuff_to_keep &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;abcdefghijklmnopqrstuvwxyz &lt;/span>&lt;span style="color:#ae81ff">\t\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2&lt;/span>&lt;span>cleaned_letters &lt;span style="color:#f92672">=&lt;/span> [x &lt;span style="color:#66d9ef">for&lt;/span> x &lt;span style="color:#f92672">in&lt;/span> lower_data &lt;span style="color:#66d9ef">if&lt;/span> x &lt;span style="color:#f92672">in&lt;/span> stuff_to_remove]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3&lt;/span>&lt;span>cleaned_string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>join(cleaned_letters)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;p>
This worked better (and yes, I know I could have used isalpha() but I
didn&amp;#39;t remember it at the time) but still had problems. We had words
that were formerly separated by punctuation with no spaces that were
now combined into new invalid words. We also had things like chapter
headings in our text and other stray words that we probably wanted to
get rid of.&lt;/p>
&lt;p>
All of this led to rich conversation among the teachers present and
can do the same in class. What do you clean? What do you keep? Is it
worth the effort to write all sorts of cleaning code to get rid of a
couple of stray bits of bad data or can we get the results we want by
leaving it in? There&amp;#39;s no universally right answer and that&amp;#39;s part of
the beauty of doing things like this with a class - it&amp;#39;s something
that can make them think.&lt;/p>
&lt;p>
Once we made our final cleaning decisions it&amp;#39;s a simple matter to
convert the long string of text into a list of words:&lt;/p>
&lt;p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>wordlist &lt;span style="color:#f92672">=&lt;/span> cleaned_string&lt;span style="color:#f92672">.&lt;/span>split()&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;p>
Now we&amp;#39;re ready to start building our bag of words but that&amp;#39;s a post
for another day.&lt;/p></description></item></channel></rss>