<jupyter_start><jupyter_text>Writing a Python function<jupyter_code>def my_function():
    pass
def my_sq(x):
    return x ** 2
my_sq(4)
def avg_2(x, y):
    return (x + y) / 2
avg_2(10, 20)
assert avg_2(10, 20) == 15.0<jupyter_output><empty_output><jupyter_text>Applying functions<jupyter_code>import pandas as pd<jupyter_output><empty_output><jupyter_text>Applying functions<jupyter_code>df = pd.DataFrame({'a':[10,20,30],
                   'b':[20,30,40]})
df
df['a'] ** 2
type(df['a'])
def my_sq(x):
    # assert isinstance(x, int)
    return x ** 2
df['a'].apply(my_sq)
def my_exp(x, e):
    return x ** e
my_exp(2, 2)
my_exp(2, 10)
df['a'].apply(my_exp, e=10)
def print_me(x):
    print(x)
print_me('hello')
df
df.apply(print_me, axis=0)
def avg_3(x, y, z):
    return (x + y + z) / 3
avg_3(0, 5, 10)
df.apply(avg_3)
import numpy as np
def avg_3_apply(col):
    # return np.sum(col) / 3
    return np.mean(col)
def avg_3_apply(col):
    x = col[0]
    y = col[1]
    z = col[2]
    return (x + y + z) / 3
df
df.apply(avg_3_apply)
df.apply(avg_3_apply, axis=1)
def avg_2_apply(row):
    x = row[0]
    y = row[1]
    return (x + y) / 2
df.apply(avg_2_apply, axis=1)
def avg_2(x, y):
    return (x + y) / 2
df
(df['a'] + df['b']) / 2
def avg_2_mod(x, y):
    if (x == 20):
        return np.NaN
    else:
        return (x + y) / 2

avg_2(df['a'], df['b'])
avg_2_mod(df['a'], df['b'])
(df['a'] == 20)
(df['a'] == 20).any()
avg_2_mod(10, 20)
avg_2_mod(20, 30)<jupyter_output><empty_output><jupyter_text>Vectorized functions<jupyter_code>import numpy as np
avg_2_mod_vec = np.vectorize(avg_2_mod)
avg_2_mod_vec(df['a'], df['b'])
@np.vectorize
def v_avg_2_mod(x, y):
    if (x == 20):
        return np.NaN
    else:
        return (x + y) / 2
v_avg_2_mod(df['a'], df['b'])
import numba
@numba.vectorize
def v_avg_2_mod_numba(x, y):
    if (x == 20):
        return np.NaN
    else:
        return (x + y) / 2
v_avg_2_mod_numba(df['a'], df['b'])
v_avg_2_mod_numba(df['a'].values, df['b'].values)
%%timeit
avg_2(df['a'], df['b'])
%%timeit
v_avg_2_mod(df['a'], df['b'])
%%timeit
v_avg_2_mod_numba(df['a'].values, df['b'].values)<jupyter_output>8.28 µs ± 170 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
{'fraction_non_alphanumeric': 0.19350473612990526, 'fraction_numerical': 0.05232295895354082, 'mean_word_length': 3.811279826464208, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '391028', 'license': 'MIT', 'n_tokens_mistral': 1089, 'n_tokens_neox': 1026, 'n_words': 222, 'path': '.notes/04-apply.ipynb', 'repo_name': 'iahmedani/pycon_2019-pandas_tutorial', 'size': '2217'}