0

I apologize in advance for asking this painstaking question.

I have a dataset that looks like this (there are about 1000 rows total, this is just the head). Each column is a z-scored blood analyte.

structure(list(alt_zscore = c(1.15628571428571, 0.899333333333333, 
NA, -0.730708333333333, 0.0963571428571428, -1.06795833333333
), alb_zscore = c(1.888599484682, 0.134900515317999, NA, 0.6745, 
-0.809400515317999, 0.6745), alp_zscore = c(2.99309375, -1.39021528321409, 
NA, -0.64982016264779, -0.274015625, -0.304302439716851), calcium_zscore = c(1.09606450959036, 
0.449665953945447, NA, -0.674500004496664, -0.33725, -0.674500004496664
), uc_ratio_zscore = c(0.691189771122184, 0.00395552487310546, 
NA, -0.955924044178282, -0.545585328858177, -0.54077986726889
), sodium_zscore = c(0.932489252756058, -0.6745, NA, -1.180375, 
0.310829750918686, -1.01175), phos_zscore = c(-0.103769544771059, 
1.21409991456333, NA, 1.39396640945733, -1.93270290026917, -1.30403359054267
), pot_zscore = c(1.07919974530892, 0.134899228372, NA, -0.404700259007998, 
1.21409890946892, -0.269801030635998), pcv_zscore = c(NA, NA, 
-0.243018626530217, 1.2141, -0.959399470734058, -0.20235), glob_zscore = c(-1.079198972062, 
0.385428307960541, NA, -0.963571690112316, -1.21409948738, -0.963571690112316
), baso_per_ul_zscore = c(NA, NA, NA, NA, NA, -1.2646875), esino_per_ul_zscore = c(NA, 
NA, 2.0877380952381, -0.108792935519412, -0.21912328042328, 1.68625
), lympho_per_ul_zscore = c(NA, NA, -0.173182432432432, -1.11988412698413, 
-0.525016216216216, 0.565295238095238), mono_per_ul_zscore = c(NA, 
NA, 1.01941477272727, -0.332159846897352, 3.01532159090909, 0.844644122370989
), neutro_per_ul_zscore = c(NA, NA, -0.82978274474743, -0.560261015649008, 
1.3692018328118, -0.69385232985532), cortisol_zscore = c(9.53660294508432, 
8.6351129251796, NA, NA, NA, NA)), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

My goal is to create columns called metab_index, imm_index, neuro_index, and dysreg_index. These are indices of 'dysregulation,' whereas any analyte that is found to be in dysregulation based on certain rules (see code below) gets a '1'. Then, the metab_index, for instance, is the # of metabolic analytes that are in dysregulation (see below code for rules of dysregulation), divided by the total # of metabolic analytes available (available meaning there is not an NA for that individual). Same goes for imm_index and neuro_index. The dysreg_index includes ALL of the analytes, not divided by physiologic system. My expected output for all "_index" variables is a number between 0 (meaning no analytes are in dysreg.) and 1 (all analytes are in dysreg).

The analytes that go into each index are: metab_index: includes alt_zscore, alb_zscore, alp_zscore, calcium_zscore, uc_ratio_zscore, sodium_zscore, phos_zscore, pot_zscore, pcv_zscore, and glob_zscore if it is too low.

imm_index: includes glob_zscore if it is too high, baso_per_ul_zscore, esino_per_ul_zscore, lympho_per_ul_zscore, mono_per_ul_zscore, and neutro_per_ul_zscore.

neuro_index: includes only cortisol_zscore.

dysreg_index: includes all of the above.

The problem arises that I have one analyte, glob_zscore, where too high of a value means it needs to be counted towards the imm_index, and too low of a value means it needs to be counted towards the metab_index. I can assign values of glob_zscore to metab_index or imm_index just fine, but my problem arises in trying to assign glob_zscore to the total dysreg_index. If glob_zscore is either too high OR too low, it should be counted towards the numerator of the dysreg_index. The dysreg_index should be a number between 0-1, but as my code is now, I am getting numbers that are >1.

Here is my code to hopefully show what I mean:

funcs <- list(
  alt_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  alb_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  alp_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  calcium_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  uc_ratio_zscore = function(z) !is.na(z) & z < quantile(z, 0.25, na.rm = TRUE),  # lower quartile (25%) is dysregulation
  sodium_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  phos_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  pot_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  pcv_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  glob_zscore = function(z) !is.na(z) & z < quantile(z, 0.25, na.rm = TRUE),  # GLOB: lower quartile (25%) is dysregulation for METABOLIC
  glob_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), # GLOB: upper quartile (75%) is dysregulation for IMMUNE
  baso_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  esino_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  lympho_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  mono_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  neutro_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  cortisol_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)) #lower (20%) or upper (80%) quintile is dysfunction
)



mapply(function(fn, x) fn(x), funcs, df[names(funcs)])

df <- df %>%
  mutate(
    metab_index = {            ## METABOLIC INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[1:10], pick(all_of(names(funcs[1:10])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[1:10]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>% 
  mutate(
    imm_index = {             ## IMMUNE INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[11:16], pick(all_of(names(funcs[11:16])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[11:16]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>% 
  mutate(
    neuro_index = {           ## NEUROENDOCRINE INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[17], pick(all_of(names(funcs[17])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[17]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>% 
  mutate(
    dysreg_index = {          ## TOTAL DYSREGULATION INDEX (includes metabolic, immune, and neuroendocrine)
      numerator <- mapply(function(fn, x) fn(x), funcs, pick(all_of(names(funcs))))
      denominator <- (!is.na(pick(all_of(names(funcs))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  )

The bug in my code is somewhere in the dysreg_index argument. My expected output is a number between 0-1, but I am getting numbers >1 at times. I know this is because I have technically two functions for glob_zscore, which likely inflates the # of functions available to pick from in the 'numerator', but I do it this way because I want to assign one function to the metab_index, and the other to the imm_index.

Any help is greatly appreciated. Thank you so much!

Mark
  • 7,785
  • 2
  • 14
  • 34
burphound
  • 161
  • 7

1 Answers1

2

I'm not sure that this counts for an answer, but this hopefully is helpful...

You're getting a warning, right?

I get this warning when I run your code:

Warning message:
There was 1 warning in `mutate()`.
ℹ In argument: `dysreg_index = { ... }`.
Caused by warning in `mapply()`:
! longer argument not a multiple of length of shorter 

Modified Code

To get a look at your numerator and denominator separately in the dysreg_index, I modified your code in the last mutate():

df2 <- df %>%
  mutate(
    metab_index = {            ## METABOLIC INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[1:10], pick(all_of(names(funcs[1:10])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[1:10]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>%
  mutate(
    imm_index = {             ## IMMUNE INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[11:16], pick(all_of(names(funcs[11:16])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[11:16]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>%
  mutate(
    neuro_index = {           ## NEUROENDOCRINE INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[17], pick(all_of(names(funcs[17])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[17]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>%
  mutate(
    # dysreg_index = {          ## TOTAL DYSREGULATION INDEX (includes metabolic, immune, and neuroendocrine)
      numerator = mapply(function(fn, x) fn(x), funcs, pick(all_of(names(funcs)))),
      denominator = (!is.na(pick(all_of(names(funcs))))) # denominator is the number of non-NA elements in a row
      # rowSums(numerator) / rowSums(denominator)
    # }
  )

This shows the unequal lengths of the numerator and denominator:

> glimpse(df2)
Rows: 6
Columns: 21
$ alt_zscore           <dbl> 1.15628571, 0.89933333, NA, -0.73070833, 0.09635714, -1.06795833
$ alb_zscore           <dbl> 1.8885995, 0.1349005, NA, 0.6745000, -0.8094005, 0.6745000
$ alp_zscore           <dbl> 2.9930937, -1.3902153, NA, -0.6498202, -0.2740156, -0.3043024
$ calcium_zscore       <dbl> 1.096065, 0.449666, NA, -0.674500, -0.337250, -0.674500
$ uc_ratio_zscore      <dbl> 0.691189771, 0.003955525, NA, -0.955924044, -0.545585329, -0.540779867
$ sodium_zscore        <dbl> 0.9324893, -0.6745000, NA, -1.1803750, 0.3108298, -1.0117500
$ phos_zscore          <dbl> -0.1037695, 1.2140999, NA, 1.3939664, -1.9327029, -1.3040336
$ pot_zscore           <dbl> 1.0791997, 0.1348992, NA, -0.4047003, 1.2140989, -0.2698010
$ pcv_zscore           <dbl> NA, NA, -0.2430186, 1.2141000, -0.9593995, -0.2023500
$ glob_zscore          <dbl> -1.0791990, 0.3854283, NA, -0.9635717, -1.2140995, -0.9635717
$ baso_per_ul_zscore   <dbl> NA, NA, NA, NA, NA, -1.264687
$ esino_per_ul_zscore  <dbl> NA, NA, 2.0877381, -0.1087929, -0.2191233, 1.6862500
$ lympho_per_ul_zscore <dbl> NA, NA, -0.1731824, -1.1198841, -0.5250162, 0.5652952
$ mono_per_ul_zscore   <dbl> NA, NA, 1.0194148, -0.3321598, 3.0153216, 0.8446441
$ neutro_per_ul_zscore <dbl> NA, NA, -0.8297827, -0.5602610, 1.3692018, -0.6938523
$ cortisol_zscore      <dbl> 9.536603, 8.635113, NA, NA, NA, NA
$ metab_index          <dbl> 0.5555556, 0.1111111, 0.0000000, 0.5000000, 0.4000000, 0.1000000
$ imm_index            <dbl> 0.0000000, 1.0000000, 0.2500000, 0.0000000, 0.4000000, 0.1666667
$ neuro_index          <dbl> 1, 1, NaN, NaN, NaN, NaN
$ numerator            <lgl[,17]> <matrix[6 x 17]>
$ denominator          <lgl[,16]> <matrix[6 x 16]>

So I went looking into what was in those two matrices:

> df2$numerator
     alt_zscore alb_zscore alp_zscore calcium_zscore uc_ratio_zscore sodium_zscore phos_zscore pot_zscore pcv_zscore glob_zscore glob_zscore
[1,]       TRUE       TRUE       TRUE           TRUE           FALSE          TRUE       FALSE      FALSE      FALSE       FALSE       FALSE
[2,]      FALSE      FALSE       TRUE          FALSE           FALSE         FALSE       FALSE      FALSE      FALSE       FALSE       FALSE
[3,]      FALSE      FALSE      FALSE          FALSE           FALSE         FALSE       FALSE      FALSE      FALSE       FALSE       FALSE
[4,]      FALSE      FALSE      FALSE          FALSE            TRUE          TRUE        TRUE       TRUE       TRUE       FALSE       FALSE
[5,]      FALSE       TRUE      FALSE          FALSE           FALSE         FALSE        TRUE       TRUE      FALSE        TRUE       FALSE
[6,]       TRUE      FALSE      FALSE          FALSE           FALSE         FALSE       FALSE      FALSE      FALSE       FALSE       FALSE
     baso_per_ul_zscore esino_per_ul_zscore lympho_per_ul_zscore mono_per_ul_zscore neutro_per_ul_zscore cortisol_zscore
[1,]              FALSE               FALSE                FALSE              FALSE                 TRUE            TRUE
[2,]              FALSE               FALSE                FALSE              FALSE                FALSE           FALSE
[3,]               TRUE               FALSE                FALSE              FALSE                FALSE           FALSE
[4,]              FALSE               FALSE                FALSE              FALSE                FALSE           FALSE
[5,]              FALSE               FALSE                 TRUE               TRUE                FALSE           FALSE
[6,]              FALSE                TRUE                FALSE              FALSE                FALSE            TRUE

And that matrix above has two columns of...yes... glob_zscore: numerator with 2x glob_zscore

And of course that duplicate doesn't exist in denominator:

> colnames(df2$denominator)
 [1] "alt_zscore"           "alb_zscore"           "alp_zscore"           "calcium_zscore"       "uc_ratio_zscore"     
 [6] "sodium_zscore"        "phos_zscore"          "pot_zscore"           "pcv_zscore"           "glob_zscore"         
[11] "baso_per_ul_zscore"   "esino_per_ul_zscore"  "lympho_per_ul_zscore" "mono_per_ul_zscore"   "neutro_per_ul_zscore"
[16] "cortisol_zscore"    

So your numerator has a possible value of 17 when your denominator maxes out at 16. (I know you acknowledged this was a problem, but I'm not sure you drilled down to this detail, so sorry if this is all stuff you knew already.)

Solution(?)

The cleanest and quickest solution to me is to add another function and then re-align your dysreg_index, which you already stated you don't want to do, but I did it anyway, and the warning message clears, and the logic now should prevent you from getting a result >1.

Added 3rd glob_zscore() function to the end of the list:

funcs <- list(
  alt_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  alb_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  alp_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  calcium_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  uc_ratio_zscore = function(z) !is.na(z) & z < quantile(z, 0.25, na.rm = TRUE),  # lower quartile (25%) is dysregulation
  sodium_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  phos_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  pot_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  pcv_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  glob_zscore = function(z) !is.na(z) & z < quantile(z, 0.25, na.rm = TRUE),  # GLOB: lower quartile (25%) is dysregulation for METABOLIC
  glob_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), # GLOB: upper quartile (75%) is dysregulation for IMMUNE
  baso_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  esino_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  lympho_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  mono_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  neutro_per_ul_zscore = function(z) !is.na(z) & z > quantile(z, 0.75, na.rm = TRUE), #upper quartile (75%) is dysregulation
  cortisol_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.20, na.rm = TRUE), quantile(z, 0.80, na.rm = TRUE)), #lower (20%) or upper (80%) quintile is dysfunction
  glob_zscore = function(z) !is.na(z) & !between(z, quantile(z, 0.25, na.rm = TRUE), quantile(z, 0.75, na.rm = TRUE)) # GLOB: lower (25%) or upper (75%) quartile is dysfunction
)

Modified your code on the dysreg_index

df2 <- df %>%
  mutate(
    metab_index = {            ## METABOLIC INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[1:10], pick(all_of(names(funcs[1:10])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[1:10]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>%
  mutate(
    imm_index = {             ## IMMUNE INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[11:16], pick(all_of(names(funcs[11:16])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[11:16]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>%
  mutate(
    neuro_index = {           ## NEUROENDOCRINE INDEX
      numerator <- mapply(function(fn, x) fn(x), funcs[17], pick(all_of(names(funcs[17])))) # order of funcs matters !
      denominator <- (!is.na(pick(all_of(names(funcs[17]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  ) %>%
  mutate(
    dysreg_index = {          ## TOTAL DYSREGULATION INDEX (includes metabolic, immune, and neuroendocrine)
      numerator <- mapply(function(fn, x) fn(x), funcs[c(1:9,12:18)], pick(all_of(names(funcs[c(1:9,12:18)]))))
      denominator <- (!is.na(pick(all_of(names(funcs[c(1:9,12:18)]))))) # denominator is the number of non-NA elements in a row
      rowSums(numerator) / rowSums(denominator)
    }
  )

NO WARNING MESSAGES!!!! (Yay!)

> glimpse(df2)
Rows: 6
Columns: 20
$ alt_zscore           <dbl> 1.15628571, 0.89933333, NA, -0.73070833, 0.09635714, -1.06795833
$ alb_zscore           <dbl> 1.8885995, 0.1349005, NA, 0.6745000, -0.8094005, 0.6745000
$ alp_zscore           <dbl> 2.9930937, -1.3902153, NA, -0.6498202, -0.2740156, -0.3043024
$ calcium_zscore       <dbl> 1.096065, 0.449666, NA, -0.674500, -0.337250, -0.674500
$ uc_ratio_zscore      <dbl> 0.691189771, 0.003955525, NA, -0.955924044, -0.545585329, -0.540779867
$ sodium_zscore        <dbl> 0.9324893, -0.6745000, NA, -1.1803750, 0.3108298, -1.0117500
$ phos_zscore          <dbl> -0.1037695, 1.2140999, NA, 1.3939664, -1.9327029, -1.3040336
$ pot_zscore           <dbl> 1.0791997, 0.1348992, NA, -0.4047003, 1.2140989, -0.2698010
$ pcv_zscore           <dbl> NA, NA, -0.2430186, 1.2141000, -0.9593995, -0.2023500
$ glob_zscore          <dbl> -1.0791990, 0.3854283, NA, -0.9635717, -1.2140995, -0.9635717
$ baso_per_ul_zscore   <dbl> NA, NA, NA, NA, NA, -1.264687
$ esino_per_ul_zscore  <dbl> NA, NA, 2.0877381, -0.1087929, -0.2191233, 1.6862500
$ lympho_per_ul_zscore <dbl> NA, NA, -0.1731824, -1.1198841, -0.5250162, 0.5652952
$ mono_per_ul_zscore   <dbl> NA, NA, 1.0194148, -0.3321598, 3.0153216, 0.8446441
$ neutro_per_ul_zscore <dbl> NA, NA, -0.8297827, -0.5602610, 1.3692018, -0.6938523
$ cortisol_zscore      <dbl> 9.536603, 8.635113, NA, NA, NA, NA
$ metab_index          <dbl> 0.5555556, 0.1111111, 0.0000000, 0.5000000, 0.4000000, 0.1000000
$ imm_index            <dbl> 0.0000000, 1.0000000, 0.2500000, 0.0000000, 0.4000000, 0.1666667
$ neuro_index          <dbl> 1, 1, NaN, NaN, NaN, NaN
$ dysreg_index         <dbl> 0.6000000, 0.3000000, 0.2000000, 0.3571429, 0.4285714, 0.1333333

It's Friday night, and I burned more time on this than I'd like to admit. I'm getting a beer... hope this helped.

ScottyJ
  • 945
  • 11
  • 16