Train The Trainer

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Thursday, 24 October 2013

Playing with R, ggplot2 and knitr

Posted on 11:21 by Unknown
Playing with R, ggplot2 and knitr

Playing with R, ggplot2 and knitr

Over the last month I have been learning R programming language that is completely FREE and used extensively in statistics and data analysis. I have been also playing with ggplot2 which is a great graphics package for R, along with knitr which was used to produce this blog post/report.

In this short demo, besides bragging with my newly acquired skillz, I wanted to give an example for power calculation in uniform (same speed) circular motion for my friend Michael Clarkson from UK. This was a part of our discussion on difference between running at the same velocity on a straight line, and running on that same velocity in the circle (air resistanc disregarded) in terms of Power production. In the simple dot mass model, in which we are going to represent human body with a dot with a mass of m we are going to disregard air resistance, body oscilations and limb movements. According to this simple model, because the velocity is same all the time, the Power output will be zero. Of course, this is not the case in real life.

The goal of this exercise is to play with vector multiplication and to check if the power is different than zero in uniform circular motion.

Let's generate some data in a data.frame called sample

# create time vector that contains our samplings time.
sample <- data.frame(time = seq(from = 0, to = 1, by = 1/1e+05))

# Calculate time difference or dt used for velocity and acceleration
# differentiation
sample$dt <- with(sample, c(NA, diff(time)))

# Create angular velocity of the object in rad/s
sample$angular.velocity <- 10

# Create radius of the circle
sample$radius <- 2

# Create mass of the object
sample$mass <- 10

This how the sample data.frame looks like

str(sample)
## 'data.frame':    100001 obs. of  5 variables:
## $ time : num 0e+00 1e-05 2e-05 3e-05 4e-05 5e-05 6e-05 7e-05 8e-05 9e-05 ...
## $ dt : num NA 1e-05 1e-05 1e-05 1e-05 1e-05 1e-05 1e-05 1e-05 1e-05 ...
## $ angular.velocity: num 10 10 10 10 10 10 10 10 10 10 ...
## $ radius : num 2 2 2 2 2 2 2 2 2 2 ...
## $ mass : num 10 10 10 10 10 10 10 10 10 10 ...

From these parameters that are already in sample data.frame we will generate x and y cordinates of the object.

# Calculate X position
sample$x <- with(sample, sin(time * angular.velocity) * radius)

# Calculate Y position
sample$y <- with(sample, cos(time * angular.velocity) * radius)

On the following graph we can se the path of the object

# Load the ggplot2 package
library(ggplot2)

ggplot(sample, aes(x = x, y = y)) + geom_point(color = "steelblue", size = 2,
alpha = 1/2) + labs(title = "Motion path") + geom_hline() + geom_vline()
plot of chunk unnamed-chunk-4

Now we have positional data and dt or time difference between sampling. We will use this to get velocity for x component and y component (velocity is a vector and we will represent it with x and y components). I beleive this is called reverse dynamics (where you estimate velocity, acceleration and force from positional and time data )

velocity_x = dx / dt

Where dx is chnage in x position between two samples (x2 - x1) and dt is change in time (we have already calculated this when designing the data.frame)

# Calculate velocity for x component
sample$vx <- with(sample, c(NA, diff(x))/dt)

# Calculate velocity for y component
sample$vy <- with(sample, c(NA, diff(y))/dt)

We can now plot velocity (x component)

ggplot(sample, aes(x = time, y = vx)) + geom_path(color = "steelblue", size = 2, 
alpha = 1/2, na.rm = TRUE) + labs(y = "Velocity x") + geom_hline()
plot of chunk unnamed-chunk-6

Having velocity data we can calculate acceleration and force, where

acceleration_x = dvelocity_x / dt

Force_x = acceleration_x X mass

# Calculate acceleration for x component
sample$ax <- with(sample, c(NA, diff(vx))/dt)

# Calculate acceleration for y component
sample$ay <- with(sample, c(NA, diff(vy))/dt)

# Calculate force for x and y directions
sample$fx <- with(sample, ax * mass)
sample$fy <- with(sample, ay * mass)

One the following picture is the graph of acceleration (x component)

ggplot(sample, aes(x = time, y = ax)) + geom_path(color = "steelblue", size = 2, 
alpha = 1/2, na.rm = TRUE) + labs(y = "Acceleration x") + geom_hline()
plot of chunk unnamed-chunk-8

Now it is time to calculate power on x and on y (scalar product)

# Calculate power for x component and y component
sample$px <- with(sample, vx * fx)
sample$py <- with(sample, vy * fy)

Here is the graph of Power (x component)

ggplot(sample, aes(x = time, y = px)) + geom_path(color = "steelblue", size = 2, 
alpha = 1/2, na.rm = TRUE) + labs(y = "Power x") + geom_hline()
plot of chunk unnamed-chunk-10

It seems that the power is fluctuating, but what happens when we calculate total power (sum of x and y component power; power is scalar so we can just add them) and visualize it?

sample$total.power <- with(sample, px + py)
ggplot(sample, aes(x = time, y = total.power)) + geom_path(color = "steelblue",
size = 2, alpha = 1/2, na.rm = TRUE) + labs(y = "Total Power") + geom_hline()
plot of chunk unnamed-chunk-11

Because centripetal force is acting on the object, and that force is perpendicular to the velocity vector, there is no work done by this force and hence power is zero. On the graph above you can see that Total Power has some value - this is constant error due sampling frequency. Higher the sample frequency, lower the error (will see the relationship later)

Another way to calculate total power would be to use scalar velocity

# Calculate scalar velocity from angular velocity and radius
sample$v = with(sample, angular.velocity * radius)

# Calculate acceleration from change in scalar velocity divided by dt
sample$a = with(sample, c(NA, diff(v))/dt)

# Calculate force acting on the object
sample$f = with(sample, a * mass)

# Calculate power
sample$p = with(sample, f * v)

# Plot power calculated
ggplot(sample, aes(x = time, y = p)) + geom_path(color = "steelblue", size = 2,
alpha = 1/2, na.rm = TRUE) + labs(y = "Total Power") + geom_hline()
plot of chunk unnamed-chunk-12

Now we can see that the total power is zero (in this simple model, NOT the real life). Let's code a function that calculates the mean total power for sampling frequency. This will involve copying the whole code above, but changing sampling frequency

mean.total.power <- function(frequency = 100) {

sample <- data.frame(time = seq(from = 0, to = 1, by = 1/frequency))
sample$dt <- with(sample, c(NA, diff(time)))
sample$angular.velocity <- 10
sample$radius <- 2
sample$mass <- 10
sample$x <- with(sample, sin(time * angular.velocity) * radius)
sample$y <- with(sample, cos(time * angular.velocity) * radius)
sample$vx <- with(sample, c(NA, diff(x))/dt)
sample$vy <- with(sample, c(NA, diff(y))/dt)
sample$ax <- with(sample, c(NA, diff(vx))/dt)
sample$ay <- with(sample, c(NA, diff(vy))/dt)
sample$fx <- with(sample, ax * mass)
sample$fy <- with(sample, ay * mass)
sample$px <- with(sample, vx * fx)
sample$py <- with(sample, vy * fy)
sample$total.power <- with(sample, px + py)
return(mean(sample$total.power, na.rm = TRUE))
}

Now we can see how does the error in Total Power behaves with different sampling frequencies. We are going to create a vector (series of data) that contains sampling frequencies - 10, 100, 1000, etc and pass that to the function. We are going to graph the error against sampling frequency. If you run this on your computer it is going to take some time.

probing.data <- data.frame(frequency = seq(from = 500, to = 1e+05, by = 1000))  # Different sampling frequencies
probing.data$power = with(probing.data, numeric(length(frequency))) # This contains the results

for (i in seq_along(probing.data$frequency)) {
probing.data$power[i] <- mean.total.power(probing.data$frequency[i])
}

ggplot(probing.data, aes(x = frequency, y = power)) + geom_path(color = "steelblue",
size = 2, alpha = 1/2, na.rm = TRUE) + labs(y = "Total Power") + geom_hline()
plot of chunk unnamed-chunk-14
If we do this on other indices, like velocity and acceleration we won't see such a change based on sampling frequency. Let's try - we just need to modify the written function to return the maximum of acceleration on x.
max.x.acceleration <- function(frequency = 100) {

sample <- data.frame(time = seq(from = 0, to = 1, by = 1/frequency))
sample$dt <- with(sample, c(NA, diff(time)))
sample$angular.velocity <- 10
sample$radius <- 2
sample$mass <- 10
sample$x <- with(sample, sin(time * angular.velocity) * radius)
sample$y <- with(sample, cos(time * angular.velocity) * radius)
sample$vx <- with(sample, c(NA, diff(x))/dt)
sample$vy <- with(sample, c(NA, diff(y))/dt)
sample$ax <- with(sample, c(NA, diff(vx))/dt)
sample$ay <- with(sample, c(NA, diff(vy))/dt)
return(max(sample$ax, na.rm = TRUE))
}

And code the same probing procedure as we did for error in total power calculus

probing.data <- data.frame(frequency = seq(from = 500, to = 1e+05, by = 1000))  # Different sampling frequencies
probing.data$acceleration = with(probing.data, numeric(length(frequency))) # This contains the results

for (i in seq_along(probing.data$frequency)) {
probing.data$acceleration[i] <- max.x.acceleration(probing.data$frequency[i])
}

ggplot(probing.data, aes(x = frequency, y = acceleration)) + geom_path(color = "steelblue",
size = 2, alpha = 1/2, na.rm = TRUE) + labs(y = "Max calculated acceleration") +
geom_hline()
plot of chunk unnamed-chunk-16

As can be seen from the plot, maximal acceleretaion (x comp) is always the same regardles of the sampling frequency.

I hope that this demonstration of R, ggplot and knitr and my simulation knowledge didn't cause major headache.

I will be using R more and more and my next project is something that will be of interest for sport scientists interested in metabolic power measurement using GPS with the goal of real-time tracking of fatigue.

Stay tuned….

Email ThisBlogThis!Share to XShare to Facebook
Posted in analysis, Biomechanics, R, statistics | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • 6 weeks running program for soccer players
    This is an article I wrote couple of months ago for one website, but it never got published, so I decided to publish it on my b...
  • Guest Article: Biological Planning, Organizing, and Programming for Physical Preparation. Part 2
    BIOLOGICAL PLANNING, ORGANIZING, AND  PROGRAMMING FOR PHYSICAL PREPARATION Part 2 Click HERE for part 1 Planning Working Backwards Many coa...
  • Research Review – Effects of different pushing speeds on bench press
    Research Review – Effects of different pushing speeds on bench press Rob Shugg from Kinetic Performance brought this very interesting study ...
  • Interview with Steve Magness
    Interview with Steve Magness In the last couple of years blog by Steve Magness “ Science of Running ” was more than the source of casual re...
  • Periodization Confusion?
    I have recently been reading Transfer of Training  (Volume 2) by Dr Anatoly Bondarchuk an...
  • Interview with Mike Boyle
      Interview with Mike Boyle There are four coaches that were highly influential on my physical preparation philosophy and practice. The firs...
  • Coincidence or not? Back to soccer
    While I was working on the 8-weeks pre-season plan for soccer  I have been contacted by the head coach of FC RAD , Marko Nikolić offering me...
  • Playbook: Understanding MODERATION through simulation
    Playbook: Understanding MODERATION through simulation Playbook: Understanding MODERATION through simulation Introduction I rece...
  • MOTORIÄŒKA ANALIZA ODBOJKAÅ KE IGRE
    Seminarski rad koji sam napisao negde u Aprilu 2010. godine pre nego sam napisao Planning and programming of training in sport games . Neki ...
  • Planning the Strength Training. Part 1
    Planning the strength training From novice to elite CHARACTERISTICS OF THE LIFTER According to Mark Rippetoe, the author of Practical Progra...

Categories

  • analysis
  • Basketball
  • Biomechanics
  • conditioning
  • dashboards
  • Download
  • ELEIKO
  • energy system development
  • Excel
  • Fasting
  • fun
  • general vs. specific
  • Good Reads
  • Guest Article
  • GymAware
  • HRV
  • IE20-10
  • injuries
  • interview
  • Italian
  • links
  • martial arts
  • MMA
  • monitoring
  • Muscles
  • Notice
  • Nutrition
  • Olympic lifting
  • On Serbian
  • Performance Analysis
  • periodization
  • Philosophy
  • Physical Therapy
  • Physiology
  • planning
  • powerlifting
  • Product
  • programming
  • Psychology
  • R
  • Random Thoughts
  • Research
  • Review
  • Roberto Sassi
  • RPE
  • RSA
  • runnings
  • screen cast
  • soccer
  • statistics
  • strength training
  • team sports
  • Theory
  • videos
  • visit
  • volleyball
  • Warm-up
  • wellness questionnaire

Blog Archive

  • ▼  2013 (54)
    • ►  December (7)
    • ►  November (8)
    • ▼  October (4)
      • Real-Time Fatigue Monitoring using Metabolic Power...
      • Random thought - Differences between locomotor pro...
      • Playing with R, ggplot2 and knitr
      • Interview with Chris Carling
    • ►  September (6)
    • ►  August (8)
    • ►  July (3)
    • ►  June (2)
    • ►  May (5)
    • ►  April (2)
    • ►  March (7)
    • ►  February (1)
    • ►  January (1)
  • ►  2012 (55)
    • ►  December (4)
    • ►  November (4)
    • ►  October (9)
    • ►  September (9)
    • ►  August (6)
    • ►  July (6)
    • ►  June (5)
    • ►  May (2)
    • ►  April (2)
    • ►  March (5)
    • ►  February (3)
  • ►  2011 (48)
    • ►  December (3)
    • ►  November (2)
    • ►  October (4)
    • ►  September (2)
    • ►  August (2)
    • ►  July (1)
    • ►  June (9)
    • ►  May (12)
    • ►  April (2)
    • ►  March (1)
    • ►  February (1)
    • ►  January (9)
  • ►  2010 (42)
    • ►  December (11)
    • ►  November (5)
    • ►  October (19)
    • ►  September (7)
Powered by Blogger.

About Me

Unknown
View my complete profile