The apply Table method

Make new columns of a table by applying custom functions to existing columns

The apply Table method

Read Inferential Thinking

Read Ch 8.1.1, which describes apply Table method.

The function signature of apply is:

tbl.apply(func, col1, …, colN)
  • func takes in the same number of arguments as columns provided. If N columns are provided, then func should take in N arguments.
  • col1, …, colN are names of columns in tbl.
  • For each row, the value in the col1 column is passed in as argument 1, the value in the col2 column is passed in as argument 2, etc.

Example

We have a weather table of high and low temperatures on each day, recorded in Farenheit. We would like to transform these temperatures to Celsius. This example creates a new column, High (C), using the apply method.

weather = Table().with_columns(
    "Day", make_array(1, 2, 3),
    "High", make_array(55.1, 57.2, 56.8),
    "Low", make_array(43.7, 46, 45.9),
    "Sky condition", make_array("Cloudy", "Sunny", "Cloudy")
)
weather
Day High Low Sky condition
1 55.1 43.7 Cloudy
2 57.2 46 Sunny
3 56.8 45.9 Cloudy
def celsius(temp):  
    """converts Fahrenheit to Celsius"""
    return (temp - 32) * 5/9

The apply method returns an array of values.

weather.apply(celsius, 'High')
array([ 12.83333333,  14.        ,  13.77777778])

We can create a new column by assigning this newly created array to a new column name.

weather.with_columns(
    "High (C)",
    weather.apply(celsius, 'High')
)
Day High Low Sky condition High (C)
1 55.1 43.7 Cloudy 12.8333
2 57.2 46 Sunny 14
3 56.8 45.9 Cloudy 13.7778

As practice, try doing the same with the temperatures in the Low column.

Applying with Strings

Task 1

Make exciting greetings by adding the Greeting column as below.

Holiday Name Greeting
Hanukkah Josh HAPPY HANUKKAH JOSH
New Year Tracy HAPPY NEW YEAR TRACY
Birthday Jaspreet HAPPY BIRTHDAY JASPREET
holidays = Table().with_columns(
    'Holiday', make_array('Hanukkah', 'New Year', 'Birthday'),
    'Name', make_array('Josh', 'Tracy', 'Jaspreet')
)
holidays
Holiday Name
Hanukkah Josh
New Year Tracy
Birthday Jaspreet

There are various solutions. One reasonable approach:

def make_greeting(holiday, name):
    return "HAPPY " + holiday.upper() + " " + name.upper()

holidays.with_columns(
    "Greeting",
    holidays.apply(make_greeting, "Holiday", "Name")
)
Holiday Name Greeting
Hanukkah Josh HAPPY HANUKKAH JOSH
New Year Tracy HAPPY NEW YEAR TRACY
Birthday Jaspreet HAPPY BIRTHDAY JASPREET

Here’s another advanced approach, using join:

def make_greeting(holiday, name):
    return ' '.join(["happy", holiday, name]).upper()

holidays.with_columns(
    "Greeting",
    holidays.apply(make_greeting, "Holiday", "Name")
)
Holiday Name Greeting
Hanukkah Josh HAPPY HANUKKAH JOSH
New Year Tracy HAPPY NEW YEAR TRACY
Birthday Jaspreet HAPPY BIRTHDAY JASPREET

Task 2 (Challenge)

Convert phone numbers. For example, 510-642-3141 should be formatted as (510) 642-3141.

Hint: Try using split. The split function returns a list of strings split by the delimiter; after conversion, lists can be indexed just like an array.

res_halls = Table().with_columns(
    'Residence Hall', 
        make_array('Unit 1', 'Unit 2', 'Unit 3', 'Foothill',
                   'Clark Kerr', 'Blackwell', 'Martinez Commons'),
    'Phone',
        make_array('510-642-3141', '510-642-3143', '510-642-5391', '510-642-9703',
                   '510-642-6290', '510-423-3740', '510-642-8517')
)
res_halls
Residence Hall Phone
Unit 1 510-642-3141
Unit 2 510-642-3143
Unit 3 510-642-5391
Foothill 510-642-9703
Clark Kerr 510-642-6290
Blackwell 510-423-3740
Martinez Commons 510-642-8517

One possible approach:

def format_phone_number(phone):
    parts = np.array(phone.split('-'))
    return "(" + parts.item(0) + ") " + parts.item(1) + "-" + parts.item(2)

res_halls.with_columns(
    "Formatted",
    res_halls.apply(format_phone_number, "Phone")
)
Residence Hall Phone Formatted
Unit 1 510-642-3141 (510) 642-3141
Unit 2 510-642-3143 (510) 642-3143
Unit 3 510-642-5391 (510) 642-5391
Foothill 510-642-9703 (510) 642-9703
Clark Kerr 510-642-6290 (510) 642-6290
Blackwell 510-423-3740 (510) 423-3740
Martinez Commons 510-642-8517 (510) 642-8517