C14008 Lesson 5: Free Day

Today, we're going to be teaching a bunch of random Julia concepts we think are interesting. Hopefully, you guys like it and find some of these concepts enjoyable. Because we're going to be dealing with more packages this week, use this block of code to instantiate packages if you're having issues loading them:

In [ ]:
using Pkg; Pkg.instantiate()

Presentations

First, let's present the problems for homework. These were:

  • Problem 22
  • Problem 42
  • Problem 10
  • Minesweeper

Writing Python in Julia

"The kids will go nuts for this one" - Christian

Julia is great in that it provides the PyCall package. You can import the PyCall package and import Python packages and run Python code.

In [ ]:
using PyCall

base64 = pyimport("base64") # importing modules with pyimport

# b64 encode a string
In [ ]:
# b64 decode a string
In [ ]:
# Import whatever modules you want (ex: math, hashlib, requests etc)

# current XKCD comic: https://xkcd.com/info.0.json

We can also run Python code in Julia with py strings. Triple quoted py"""""" strings are equivalent to an exec call and return nothing! Single quoted py"" strings are equivalent to using eval and allow you to call Python functions and access python variables.

In [ ]:
# writing a method using a triple quoted string

# calling the method

# evaluating stuff

Writing Julia in Python

We can also write Julia in Python using the julia package in Python. You can sorta just import Julia modules into Python.

In [ ]:
# going to the terminal to run python-jl

Writing Julia in Julia

Now we're going to be covering some more advanced Julia programming features. First up, Julia macros! A Julia macro returns a piece of code, wrapped in a :( code ) that is executed when you call the macro. So, it's kinda like a function that returns a function, which then, when you call it, calls the code it returns.

In [ ]:
# Write sayhello macro

# call sayhello

We can also pass functions to our macros, so our macros can control how the functions execute, like Python decorators.

In [ ]:
isAllowed = false

# Write security macro
In [ ]:
# test security macro

Let's talk about Symbols

A Symbol in Julia is sort of in between a string, but they're treated similar to the names of functions or variables. Symbols start with a colon : and can have any name you want.

In [ ]:
# Defining some symbols

We can use symbols to talk about functions or variables. Notice that if we eval a symbol, we get the thing it represents.

In [ ]:
# eval-ing some symbols

So this gets really neat, because now we can use symbols as standins for function names, especially in common with the @eval macro, which does eval(quote( code )). Say, we want to make a unit circle:

In [ ]:
for n = 1:8, func = [:sin, :cos, :tan]
    result = @eval $func($n*π/4)  # when you use a symbol with eval, you need to use the string interpolation syntax, because we're filling in variables in a code expression
    
    println("$func($n*π/4) is " * string(result))
end

In short, Symboleval call → thing the symbol represents (function, variable). It's beyond the scope of this class, but Symbols and Exprs allow you to generate Julia code really quickly, which is documented in the Metaprogramming section of the Julia docs.

Let's talk about Exprs

An Expr in Julia is a piece of code that can be evaluated, kind of like an "expanded" Symbol. They're what a macro returns. If we want to get extra fancy, we can talk about quote blocks. They can contain code and we can call them with the eval(code) method.

In [ ]:
# Defining and calling a quote block

# Writing a macro to return a quote

Data Science bits

DataFrames.jl

The Julia DataFrames package is intended to be a little like the Python pandas DataFrames class, giving us easy access to our data. For this, I've pulled the class roster.

In [ ]:
using CSV, DataFrames

# pulling in roster and setup
students = DataFrame(CSV.File("C14008 Roster and Setup - Attendance Wk 2.csv"))

We access DataFrames similarly to Julia matrices, df[rows, cols].

In [ ]:
# pull attendance for 1-Aug and Student Name

We can use the describe method to learn overall information about our DataFrame, like the percentage of students that showed up to each class!

In [ ]:
# describe students
describe(students)[:, Not(["min", "max", "nmissing"])]

We can also add conditions while we're picking which rows and columns we want, by specifying the "1-Aug" column in the rows parameter.

In [ ]:
# only pick students that showed up for class on August 1st
In [ ]:
# A closer look at how this actually works

Plotting stuff with Plots

Now, let's try and use the Plots package to visualize some of this data. First, we need to import the Plots package and tell it we're going to use the GR backend.

In [ ]:
using Plots
gr()

Now, let's just plot some mathematical functions, by using a function in place of y.

In [ ]:
# plotting functions

Now, to plot some data out of our Data Frame, we can plot the number of students that showed up to class on each date:

In [ ]:
dates = ["18-Jul", "25-Jul", "1-Aug"]
bar([sum(col) for col in eachcol(students[:, dates])], xaxis=("date"))

Plotting daily weather data for the memes

In [ ]:
# pull temp data
using PyCall
py"""
import requests
weather = requests.get("https://forecast.weather.gov/MapClick.php?lat=30.33&lon=-97.74&unit=0&lg=english&FcstType=json").json()
"""

data = py"weather"
In [ ]:
# plot temperature data
plot(parse.(Int, data["data"]["temperature"]), yaxis=("temperature", (75,100)))

Homework

There's actually no homework! Today's lecture was just mostly for fun, and next lecture is challenge day. If you're itching for something to do, then go have some fun solving Euler problems. Otherwise, sit back, relax, ask questions, and get ready for next week!