<jupyter_start><jupyter_text>Final Assignment, Part I* Name: _WISDM Smartphone and Smartwatch Activity and Biometrics Dataset Data Set_* Source: https://archive.ics.uci.edu/ml/datasets/WISDM+Smartphone+and+Smartwatch+Activity+and+Biometrics+Dataset+* License: Must cite:> Smartphone and Smartwatch-Based Biometrics Using Activities of Daily Living. IEEE Access, 7:133190-133202, Sept. 2019.* Filesize: * Total Zip: 302MB * Data: 1.1GB (582MB + 205MB + 196MB + 109MB)* Data File Count: 204 (51 * 4)* Number of Instances: 15630426<jupyter_code>%matplotlib widget

from pathlib import Path

import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

import numpy as np
import pandas as pd

# Thanks to `ImportanceOfBeingErnest` from https://stackoverflow.com/questions/47404653/pandas-0-21-0-timestamp-compatibility-issue-with-matplotlib
pd.plotting.register_matplotlib_converters()

input_dirpath = Path('../data/raw/wisdm/raw')
processed_dirpath = Path('../data/processed/wisdm/')
ref_dirpath = Path('../references')

activity_key_path = ref_dirpath / 'wisdm_activity_key.txt'

DEBUG=True
def release_plt_mem():
    if not DEBUG:
        return
    try:
        # release memory if needed
        plt.close('all')
    except:
        pass

activity_key = {v: k for k, v in [line.strip().split(' = ') for line in activity_key_path.read_text().strip().split('\n')]}
# '| Keys | Activity |\n|:-:|:-:|' + '\n'.join(['|{}|{}|'.format(k, v) for k, v in activity_key.items()])<jupyter_output><empty_output><jupyter_text>Data Information> from Documentation| Keys | Activity ||:-:|:-:||A|walking||B|jogging||C|stairs||D|sitting||E|standing||F|typing||G|teeth||H|soup||I|chips||J|pasta||K|drinking||L|sandwich||M|kicking||O|catch||P|dribbling||Q|writing||R|clapping||S|folding|| Field name | Type | Description | Range ||:--|:--|:--|:--|| Subject-id |  Symbolic numeric identififier. | Uniquely identifyies the subject. | 1600-1650. || Activity code | Symbolic single letter. | Identifies a specific activity as listed in Table 2. | A-S (no “N” value) || Timestamp  | Integer. | Linux time | >= 1-1-1970 00\:00\:00.0+00\:00 || x | Numeric: real.  | Sensor value for x axis. | May be positive or negative. || y | Numeric: real.  | Sensor value for y axis. | May be positive or negative. || z | Numeric: real.  | Sensor value for z axis. | May be positive or negative. |<jupyter_code># process data for ease of access - only run once
            
def concat_subject_data_by_device_type(reimport=False):
    """ Construct files containing all subjects and activities for each device and sensor type. """
    
    try:
        # This will build a dictionary for the files
        # This can take awhile as the files are large
        data_filepaths = list(processed_dirpath.glob('wisdm_*.csv'))
        
        if not reimport and len(list(data_filepaths)) == 4:
            return {f.stem.replace('wisdm_', ''): pd.read_csv(f, parse_dates=['timestamp']) for f in data_filepaths}
    except FileNotFoundError:
        pass
    
    import zipfile

    df_dict = {}
    # from data documentation
    headers = ['subject_id', 'activity_code', 'timestamp', 'x','y','z']

    for f in input_dirpath.glob('**/*.zip'):
        unzip_dirpath = f.parent / f.stem
        if not unzip_dirpath.exists():
            with zipfile.ZipFile(str(f),'r') as fd:
                fd.extractall(str(f.parent))

    for f in input_dirpath.glob('raw/**/*.txt'):
        if not any([name in str(f) for name in ['watch', 'phone']]):
            continue

        split_path = f.parts
        device_type, sensor_type  = split_path[-3:-1]
        data_src = '{}_{}'.format(device_type, sensor_type)

        filename = output_dirpath / 'wisdm_{}.csv'.format(data_src)
        if filename.exists():
            continue

        new_df = pd.read_csv(f, names=headers, parse_dates=['timestamp'], infer_datetime_format=False)
        new_df['timestamp'] = [pd.to_datetime(int(ts), utc=True) for ts in new_df['timestamp']]
        
        # remove idiosyncratic endline symbol
        new_df.iloc[:,-1] = new_df.iloc[:,-1].str.replace(';', '')
        
        if dfs.get(data_src) is None:
            df_dict[data_src] = new_df
        else:
            df_dict[data_src] = dfs[data_src].append(new_df)

    for data_src, df in df_dict.items():
        df.to_csv(output_dirpath / 'wisdm_{}.csv'.format(data_src), index=False)

    return df_dict
    
dfs = concat_subject_data_by_device_type(reimport=False)
display(dfs.get('phone_accel').head())
display(dfs.get('phone_accel').tail())
display(dfs.get('phone_accel').dtypes)
display(dfs.get('watch_accel').dtypes)
df = dfs.get('phone_accel').groupby('activity_code')
np.median(df.get_group('A')[['x', 'y', 'z']], axis=0)<jupyter_output><empty_output><jupyter_text>From page 2 of the documentation:>For the accelerometer sensor, the units are$m/s^2$, ... Note that the force of gravity on Earth,which affects the accelerometer readings, is $9.8m/s^2$.Note: *y* axis is Vertical, not *z*. Why is this using an image processing system?| Axis | Direction ||:-:|:-:||x|Forward/Backward||y|Up/Down||z|Left/Right|<jupyter_code>df = dfs.get('phone_accel').groupby(['subject_id', 'activity_code'])
df_sub = df.get_group((1600, 'A'))
display(df_sub['y'].head())
display(df_sub['y'].mean())<jupyter_output><empty_output><jupyter_text>Shift To Origin / Mean FunctionsUsed to set the first index or the mean as the origin, substracting it from subsequent values.This helps remove artifacts which bias the data when comparing sets<jupyter_code>def shift_to_origin(df_):
    """  Adjust values using initial index as `origin`  (otherwise inital bias takes over during cumulative summation). """
    return df_.assign(**{col: df_[col] - df_[col].iloc[0] for col in ['x', 'y', 'z']})

def shift_to_mean(df_):
    """ Adjust values using mean as `origin` (otherwise inital bias takes over during cumulative summation). """
    return df_.assign(**{col: df_[col] - df_[col].mean() for col in ['x', 'y', 'z']})
df = dfs.get('phone_accel').groupby(['subject_id', 'activity_code'])
df_sub = df.get_group((1600, 'A'))

for name, fn in [('shift_to_origin', shift_to_origin), ('shift_to_mean', shift_to_mean)]:
    df_sub_adj = fn(df_sub)
    # display(df_sub_adj.nlargest(5, columns='y').append(df_sub_adj.nsmallest(5, columns='y')))
    print('\n>>>\n>>> ' + name.replace('_', ' ').capitalize() + ' <<<\n>>>')
    display(df_sub_adj.sort_values(by='y'))
    print('\n>   Mean Values after Tare')
    display(pd.DataFrame(np.round(df_sub_adj.mean(), decimals=6)).T)

# df_sub_adj = tare_to_mean(df_sub)
# # display(df_sub_adj.nlargest(5, columns='y').append(df_sub_adj.nsmallest(5, columns='y')))
# display(df_sub_adj.sort_values(by='y'))
# display(pd.DataFrame(np.round(df_sub_adj.mean(), decimals=5)))<jupyter_output>>>>
>>> Shift to origin <<<
>>><jupyter_text>Note$y$ should be nearly $0$ with gravity taken into account. `Tare To Mean` works well.  Coordinate SummationIf acceleration data is treaded as *instantaneous* acceleration ($\bf{a}$), taking the cumulative sum as a *knockoff* version of an integral over $\bf{a}$ gives us a velocity ($\bf{v}$).This is probably better stated, informally speaking, as a *pseudo*-velocity. **NOTE**: Technically, this should be divided by the frame rate (~25fps). For exploratory purposes, this probably isn't necessary to get the gist of the space.<jupyter_code>def coord_summation(df_, combine=False):
    """ For cumulatively sum coordinate vectors across time"""
    return df_.assign(**{'{}{}'.format(col, '_sum' if combine else ''): vals.cumsum(axis=0) for col, vals in df_[['x', 'y', 'z']].items()})
df_sub_adj = shift_to_mean(df_sub)
df_sub_sum = coord_summation(df_sub_adj)
df_sub_samp = df_sub_adj.iloc[:1000]
df_sub_sum = df_sub_sum.iloc[:1000]

# display({col: df_sub_sum[['x', 'y', 'z']].cumsum(axis=0) for col, vals in df_sub_sum[['x', 'y', 'z']].items()})
mins = df_sub_sum[['x','y','z']].aggregate('min')
maxs = df_sub_sum[['x','y','z']].aggregate('max')

mins.name = 'minimums'
maxs.name = 'maximums'

display(mins)
display(maxs)

total_min = mins.min()
total_max = maxs.max()

abs_minmax = np.max(np.abs([total_min, total_max]))

print()
print('Total Minimum: {:.04f}'.format(total_min))
print('Total Maximum: {:.04f}'.format(total_max))
print('Absolute MinMax: {:.04f}'.format(abs_minmax))
def get_abs_minmax(df_):
    total_min = df_[['x','y','z']].aggregate('min').min()
    total_max = df_[['x','y','z']].aggregate('max').max()
    return np.max(np.abs([total_min, total_max]))<jupyter_output><empty_output><jupyter_text>Acceleration Analysis> in $m/s^2$<jupyter_code>release_plt_mem()

df_sub_sum = coord_summation(df_sub_adj)
df_sub_samp = df_sub_adj.iloc[:1000]
df_sub_sum = df_sub_sum.iloc[:1000]

abs_minmax = get_abs_minmax(df_sub_sum) + 100

""" Start Plot """
fig, axs = plt.subplots(3,1,sharex=True)
fig.suptitle('Phone Accelerometer for Subject #1600 - Walking')
ax_vert, ax_lng, ax_lat = axs

ax_vert.plot(df_sub_samp['timestamp'], df_sub_sum['y'])
ax_lng.plot(df_sub_samp['timestamp'], df_sub_sum['x'])
ax_lat.plot(df_sub_samp['timestamp'], df_sub_sum['z'])

for ax in axs:
    ax.set_ylim(-(abs_minmax), abs_minmax)

ax_vert.set_ylabel('Y (Vertical Axis)')
ax_lng.set_ylabel('X (Longitudnal Axis)')
ax_lat.set_ylabel('Z (lateral Axis)')

ax_vert.grid()
ax_lng.grid()
ax_lat.grid()

ax_lat.set_xlabel('Time')

fig.canvas.layout.width = '1600px'
fig.canvas.layout.height = '1200px'

plt.show()
df = dfs.get('phone_accel')
df = df[(df['subject_id'] == 1600)]

def get_abs_subject_max(df_):
    return np.max([get_abs_minmax(coord_summation(shift_to_mean(df_[(df_['activity_code'] == key)]))[['x', 'y', 'z']]) for key, activity in activity_key.items()])

get_abs_subject_max(df)
from mpl_toolkits.mplot3d import Axes3D

def plot_activity_accel_over_time(df_, subject_id=1600, release_mem=False):
    if release_mem:
        release_plt_mem()
    df_subject = df_[(df_['subject_id']==subject_id)]

    fig_ = plt.figure()
    ax = fig_.add_subplot(111, projection='3d')

    subject_abs_max = get_abs_subject_max(df_subject)

    for key, activity in activity_key.items():
        df_subject_activity = shift_to_mean(df_subject[(df_subject['activity_code']==key)][['x', 'y', 'z']])
        df_subject_sum = coord_summation(df_subject_activity)

        ax.plot(df_subject_sum['x'], df_subject_sum['z'], df_subject_sum['y'], label=activity)

        ax.set_xlabel('Longitudnal')
        ax.set_ylabel('Lateral')
        ax.set_zlabel('Vertical')

        ax.set_xlim(-subject_abs_max, subject_abs_max)
        ax.set_ylim(-subject_abs_max, subject_abs_max)
        ax.set_zlim(-subject_abs_max, subject_abs_max)

    fig_.legend(title='Activity')
    fig_.suptitle('Subject #1600\'s Summed Acceleration per Activity in 3D-Space Over Time.')
    
    return fig_
fig = plot_activity_accel_over_time(dfs.get('phone_accel'), 1600)
fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.show()
fig = plot_activity_accel_over_time(dfs.get('watch_accel'), subject_id=1620)

fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.show()<jupyter_output><empty_output><jupyter_text>Gyroscopic Analysis>(for) the gyroscope sensor, the units are $\theta/s$Not sure about this wrt this data:| Axis | Envelope ||:-:|:-:||x|roll||y|pitch||z|yaw|**NOTE**: It is unclear if these data run into gimble-lock situations. Given the activity domain, it is doubtful this would be an issue.<jupyter_code>df_watch_gyro = dfs.get('watch_gyro')
df_phone_gyro = dfs.get('phone_gyro')

subject = 1650

df_watch_gyro = df_watch_gyro[df_watch_gyro['subject_id'] == subject]
df_phone_gyro = df_phone_gyro[df_phone_gyro['subject_id'] == subject]

max_frames = 200

# display(df_watch_gyro.head())
release_plt_mem()
# https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.subplots.html?highlight=subplots#matplotlib.pyplot.subplots
fig, axs = plt.subplots(1,2, subplot_kw=dict(polar=True))

ax_watch, ax_phone = axs

#
# Watch
#

# Activity D: Sitting
df = shift_to_mean(df_watch_gyro[df_watch_gyro['activity_code']=='D'].iloc[:max_frames])
ax_watch.plot(df.index, df['x'], label=activity_key.get('D'))

# Activity Q: Writing
df = shift_to_mean(df_watch_gyro[df_watch_gyro['activity_code']=='Q'].iloc[:max_frames])
ax_watch.plot(df.index, df['x'], label=activity_key.get('Q'))

#
# Phone
#

# Activity D: Sitting
df = shift_to_mean(df_phone_gyro[df_phone_gyro['activity_code']=='D'].iloc[:max_frames])
ax_phone.plot(df.index, df['x'], label=activity_key.get('D'))

# Activity Q: Writing
df = shift_to_mean(df_phone_gyro[df_phone_gyro['activity_code']=='Q'].iloc[:max_frames])
ax_phone.plot(df.index, df['x'], label=activity_key.get('Q'))


for ax in axs:
    ax.set_rlim(ax.get_rmin(), 8)
    ax.set_xlabel('Gyroscope Rotation (in radians)')
    ax.text(np.radians(ax.get_rlabel_position()+10), ax.get_rmax() - 2, 'Time', rotation=ax.get_rlabel_position() + 5, ha='center',va='center')

fig.legend(title='Activity')    
fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.show()
df_watch_gyro = dfs.get('watch_gyro')
df_phone_gyro = dfs.get('phone_gyro')

subject = 1650

df_watch_gyro = df_watch_gyro[df_watch_gyro['subject_id'] == subject]
df_phone_gyro = df_phone_gyro[df_phone_gyro['subject_id'] == subject]


# display(df_watch_gyro.head())
release_plt_mem()
# https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.subplots.html?highlight=subplots#matplotlib.pyplot.subplots
fig, axs = plt.subplots(2,1)

ax_watch, ax_phone = axs

#
# Watch
#

# Watch Activity A: Walking
df = coord_summation(shift_to_mean(df_watch_gyro[df_watch_gyro['activity_code']=='A'].reset_index(drop=True)))
ax_watch.plot(df['x'].index, df['x'], label='{}'.format(activity_key.get('A')))

# Watch Activity D: Sitting
df = coord_summation(shift_to_mean(df_watch_gyro[df_watch_gyro['activity_code']=='D'].reset_index(drop=True)))
ax_watch.plot(df['x'].index, df['x'], label='{}'.format(activity_key.get('D')))

# watch Activity Q: Writing
df = coord_summation(shift_to_mean(df_watch_gyro[df_watch_gyro['activity_code']=='Q'].reset_index(drop=True)))
ax_watch.plot(df['x'].index, df['x'], label='{}'.format(activity_key.get('Q')))
ax_watch.set_title('Watch Gyroscope')

#
# Phone
#

# Phone Activity A: Walking
df = coord_summation(shift_to_mean(df_phone_gyro[df_phone_gyro['activity_code']=='A'].reset_index(drop=True)))
ax_phone.plot(df['x'].index, df['x'], label='{}'.format(activity_key.get('A')))

# Phone Activity D: Sitting
df = coord_summation(shift_to_mean(df_phone_gyro[df_phone_gyro['activity_code']=='D'].reset_index(drop=True)))
ax_phone.plot(df['x'].index, df['x'], label='{}'.format(activity_key.get('D')))

# watch Activity Q: Writing
df = coord_summation(shift_to_mean(df_phone_gyro[df_phone_gyro['activity_code']=='Q'].reset_index(drop=True)))
ax_phone.plot(df['x'].index, df['x'], label='{}'.format(activity_key.get('Q')))
ax_phone.set_title('Phone Gyroscope')

for ax in axs:
    ax.grid()
    ax.set_xlabel('Time')
    ax.set_ylabel('Cumulative Radians per Second')
    ax.legend()

   
fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.show()
df_watch_accel = dfs.get('watch_accel')
df_phone_accel = dfs.get('phone_accel')

# display(len(set(df_watch_accel['activity_code'])))
# display((set(df_phone_accel['subject_id'])))

# subject = 1650
# activity_code = 'A'

# df_watch_accel = coord_summation(shift_to_mean(df_watch_accel[(df_watch_accel['subject_id'] == subject) & (df_watch_accel['activity_code'] == activity_code)]), True).reset_index(drop=True)
# df_phone_accel = coord_summation(shift_to_mean(df_phone_accel[(df_phone_accel['subject_id'] == subject) & (df_phone_accel['activity_code'] == activity_code)]), True).reset_index(drop=True)

# display(df_watch_accel)
# display(df_phone_accel)

# fig, axs = plt.subplots(1,1)
# ax1 = axs

# ax1.plot(df_watch_accel['y_sum'])
# ax1.plot(df_phone_accel['y_sum'])

# fig.show()<jupyter_output><empty_output><jupyter_text>Gyroscope + AccelerometerTo get the actual heading of the device, the coordinates need to be rotated. A rotation matrix might be of use (taken from [Wolfram-Alpha - Rotation Matrix](http://mathworld.wolfram.com/RotationMatrix.html))Rotation around the x-axis, where $\alpha = \text{x_gyro}$:$$R_x(\alpha) = \begin{bmatrix}    1 & 0 & 0 \\    0 & cos\;\alpha & -sin\;\alpha \\    0 & sin\;\alpha & cos\;\alpha \\\end{bmatrix}\\[2em]$$Rotation around the y-axis, where $\beta = \text{y_gyro}$:$$R_y(\beta) = \begin{bmatrix}cos\;\beta & 0 & sin\;\beta \\0 & 1 & 0 \\-sin\;\beta & 0 & cos\;\beta \\\end{bmatrix}\\[2em]$$Rotation around the z-axis, where $\gamma = \text{z_gyro}$$$R_z(\gamma) = \begin{bmatrix}cos\;\gamma & -sin\;\gamma & 0 \\sin\;\gamma & cos\;\gamma & 0 \\0 & 0 & 1 \\\end{bmatrix}$$Note: Rotations are done in $R_{zyx}$ order$$\begin{bmatrix}cos\;\gamma & -sin\;\gamma & 0 \\sin\;\gamma & cos\;\gamma & 0 \\0 & 0 & 1 \\\end{bmatrix}\begin{bmatrix}cos\;\beta & 0 & sin\;\beta \\0 & 1 & 0 \\-sin\;\beta & 0 & cos\;\beta \\\end{bmatrix}\begin{bmatrix}    1 & 0 & 0 \\    0 & cos\;\alpha & -sin\;\alpha \\    0 & sin\;\alpha & cos\;\alpha \\\end{bmatrix}$$<jupyter_code>def series_3d_rotation(_ser, rot_labels=['x_accel', 'y_accel', 'z_accel']):
    coords = _ser[['x_accel', 'y_accel', 'z_accel']].astype(np.float64)
    rots = _ser[['x_gyro', 'y_gyro', 'z_gyro']].astype(np.float64)
    rots.index = ['x', 'y', 'z']
    cos = rots.apply(np.cos)
    cos.name = 'cosine'
    sin = rots.apply(np.sin)
    sin.name = 'sine'
    ones = 1.
    zeros = 0.

    x_rot = np.matrix([
        [ones , zeros,  zeros], 
        [zeros, cos.x, -sin.x],
        [zeros, sin.x,  cos.x]
    ])
    
    y_rot = np.matrix([
        [ cos.y, zeros, sin.y], 
        [ zeros, ones , zeros],
        [-sin.y, zeros, cos.y]
    ])
    
    z_rot = np.matrix([
        [ cos.z, -sin.z, zeros], 
        [ sin.z,  cos.z, zeros],
        [ zeros,  zeros,  ones]
    ])
    
    rot_coords = np.round(np.dot(np.dot(z_rot, np.dot(y_rot, x_rot)), coords), decimals=10)[0]
    new_coords = pd.Series(rot_coords, index=rot_labels)
    
    return new_coords<jupyter_output><empty_output><jupyter_text>This is a $90^\circ$ rotation clockwise around the y-axis.$$R_{zyx}(0 \; 90^\circ \; 0)    \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} =     \begin{bmatrix}0 \\ 0 \\ -1\end{bmatrix}$$ $$R_{zyx}(0 \; 90^\circ \; 0)\begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} =\begin{bmatrix}0 & -1 & 0 \\1 & 0 & 0 \\0 & 0 & 1\end{bmatrix} \begin{bmatrix}0 & 0 & 1 \\0 & 1 & 0 \\-1 & 0 & 0\end{bmatrix}\begin{bmatrix}1 & 0 & 0 \\0 & 0 & -1 \\0 & 1 & 0\end{bmatrix}\begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix}= \begin{bmatrix}0 \\ 0 \\ -1\end{bmatrix}$$<jupyter_code>test_ser = pd.Series({'x_accel': 1, 'y_accel': 0, 'z_accel': 0, 'x_gyro': 0, 'y_gyro': np.pi/2, 'z_gyro': 0})

print('Original')
display(test_ser.to_frame().loc[['x_accel', 'y_accel', 'z_accel']])

test_rot = series_3d_rotation(test_ser).to_frame()
print('Rotated clockwise by pi/2 around the y-axis.')
display(test_rot)
test_df = pd.DataFrame({'x_accel': 1, 'y_accel': 0, 'z_accel': 0, 'x_gyro': 0, 'y_gyro': np.pi/2, 'z_gyro': 0}, index=[0])
rot_test_df = test_df.apply(series_3d_rotation, axis=1)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot([0, test_df.x_accel.iloc[0]], [0, test_df.y_accel.iloc[0]], [0, test_df.z_accel.iloc[0]], label='Original Vector')
ax.plot([0, rot_test_df.x_accel.iloc[0]], [0, rot_test_df.y_accel.iloc[0]], [0, rot_test_df.z_accel.iloc[0]], label='Rotated Vector')
fig.legend()
fig.canvas.layout.width = '600px'
fig.canvas.layout.height = '600px'

fig.show()
watch_df = pd.read_csv('../data/processed/wisdm/merged_sensors/watch/1600_watch.csv').drop(columns='timestamp')
watch_df.head()
def shift_to_mean(df_, columns=['x_accel', 'y_accel', 'z_accel']):
    """ Adjust values using mean as `origin` (otherwise inital bias takes over during cumulative summation). """
    return df_.assign(**{col: df_[col] - df_[col].mean() for col in columns})<jupyter_output><empty_output><jupyter_text>Original Activity Data<jupyter_code>act_grp_a = watch_df.groupby('activity_code').get_group('A')
act_grp_a.head()[['x_accel', 'y_accel', 'z_accel']]<jupyter_output><empty_output><jupyter_text>Aggregate Sum of Original Activity Data<jupyter_code>sum_act_grp_a = act_grp_a[['x_accel', 'y_accel', 'z_accel']].cumsum(axis=0)
sum_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Aggregate Sum of Rotated Original Activity Data<jupyter_code>sum_rot_act_grp_a = act_grp_a.apply(series_3d_rotation, axis=1).cumsum(axis=0)
sum_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Aggregate Sum of Standardized Original Activity Data<jupyter_code>sum_std_act_grp_a = shift_to_mean(act_grp_a)[['x_accel', 'y_accel', 'z_accel']].cumsum(axis=0)
sum_std_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Standardize, Rotate, Sum1. Standardize2. Rotate3. Aggregate Sums Standardized Original Activity Data<jupyter_code>std_act_grp_a = shift_to_mean(act_grp_a)
std_act_grp_a.head()[['x_accel', 'y_accel', 'z_accel']]<jupyter_output><empty_output><jupyter_text>Standardized, then Rotated, Activity Data<jupyter_code>rot_std_act_grp_a = std_act_grp_a.apply(series_3d_rotation, axis=1)
rot_std_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Aggregate Sum of Rotated Standardized Data<jupyter_code>sum_rot_std_act_grp_a = rot_std_act_grp_a.cumsum(axis=0)
sum_rot_std_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Rotate, Standardize, Sum1. Rotate2. Standardize3. Aggregate Sums Rotated Original Activity Data<jupyter_code>rot_act_grp_a = act_grp_a.apply(series_3d_rotation, axis=1)
rot_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Rotated, then Standardized, Activity Data<jupyter_code>std_rot_act_grp_a = shift_to_mean(rot_act_grp_a)
std_rot_act_grp_a.head()<jupyter_output><empty_output><jupyter_text>Aggregate Sum of Standardized Rotated Data<jupyter_code>sum_std_rot_act_grp_a = std_rot_act_grp_a.cumsum(axis=0)
sum_std_rot_act_grp_a.head()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(sum_act_grp_a.x_accel, sum_act_grp_a.y_accel, sum_act_grp_a.z_accel, label='Original')
ax.plot(sum_std_act_grp_a.x_accel, sum_std_act_grp_a.y_accel, sum_std_act_grp_a.z_accel, label='Standardized Original')
ax.plot(sum_rot_act_grp_a.x_accel, sum_rot_act_grp_a.y_accel, sum_rot_act_grp_a.z_accel, label='Rotated Original')
ax.plot(sum_std_rot_act_grp_a.x_accel, sum_std_rot_act_grp_a.y_accel, sum_std_rot_act_grp_a.z_accel, label='Standardized Rotated Data')
ax.plot(sum_rot_std_act_grp_a.x_accel, sum_rot_std_act_grp_a.y_accel, sum_rot_std_act_grp_a.z_accel, label='Rotated Standardized Data')

ax.set_xlim(-20000, 20000)
ax.set_ylim(-20000, 20000)
ax.set_zlim(-20000, 20000)

fig.legend()
fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.show()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot([], [], [])
ax.plot(sum_std_act_grp_a.x_accel, sum_std_act_grp_a.y_accel, sum_std_act_grp_a.z_accel, label='Standardized Original')
ax.plot([], [], [])
ax.plot(sum_std_rot_act_grp_a.x_accel, sum_std_rot_act_grp_a.y_accel, sum_std_rot_act_grp_a.z_accel, label='Standardized Rotated Data')
ax.plot(sum_rot_std_act_grp_a.x_accel, sum_rot_std_act_grp_a.y_accel, sum_rot_std_act_grp_a.z_accel, label='Rotated Standardized Data')

fig.legend()
fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.show()

fig, axs = plt.subplots(3,1)

axs[0].plot(sum_act_grp_a.x_accel, label='Original Data')
axs[0].plot(sum_std_act_grp_a.x_accel, label='Standardized Data')
axs[0].plot(sum_rot_act_grp_a.x_accel, label='Rotated Data')
axs[0].plot(sum_std_rot_act_grp_a.x_accel, label='Standardized Rotated Data')
axs[0].plot(sum_rot_std_act_grp_a.x_accel, label='Rotated Standardized Data')
axs[0].set_ylabel('X Axis')
axs[0].set_ylim(-1000, 1000)

axs[1].plot(sum_act_grp_a.y_accel)
axs[1].plot(sum_std_act_grp_a.y_accel)
axs[1].plot(sum_rot_act_grp_a.y_accel)
axs[1].plot(sum_std_rot_act_grp_a.y_accel)
axs[1].plot(sum_rot_std_act_grp_a.y_accel)
axs[1].set_ylabel('Y Axis')
axs[1].set_ylim(-1000, 1000)

axs[2].plot(sum_act_grp_a.z_accel)
axs[2].plot(sum_std_act_grp_a.z_accel)
axs[2].plot(sum_rot_act_grp_a.y_accel)
axs[2].plot(sum_std_rot_act_grp_a.z_accel)
axs[2].plot(sum_rot_std_act_grp_a.z_accel)
axs[2].set_ylabel('Z Axis')
axs[2].set_xlabel('Timestep')
axs[2].set_ylim(-1000, 1000)



fig.canvas.layout.width = '1200px'
fig.canvas.layout.height = '1200px'

fig.legend()
fig.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16887282767581616, 'fraction_numerical': 0.02099236641221374, 'mean_word_length': 5.469398476490675, 'pattern_counts': {'":': 0, '<': 82, '<?xml version=': 0, '>': 101, 'https://': 4, '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': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '269638', 'license': 'FTL', 'n_tokens_mistral': 10123, 'n_tokens_neox': 9697, 'n_words': 1645, 'path': 'notebooks/SmartPhoneWatchActivity.ipynb', 'repo_name': 'tretomaszewski/F19_IS590DV_Final', 'size': '24628'}