Skip to contents

Tutorial

  • How to import LabChart’s HRV report file (.txt) into a tidy tibble with 1 subject per rows.

Export HRV report file

After you’ve analysed the HRV data in LabChart, follow these steps to export HRV report:

Go to menu HRV -> Export Report... -> save file as .txt

Open that file, it should look like this:

As you can see, the text file is slightly formatted and store data in key-value pairs (mostly).

How to transform it so that a data analysis can be performed?

To process this data for further analysis, one approach is to convert it to a table-like data structure which, in R, is a data frame (or tibble). The design of this data frame should be tidy, meaning column names are variables, and each rows represent a single subject. (As in this example, it should be converted to a 1 row data frame.)

It takes time and effort to manually transforms this into a table which can be even harder when the number of subject grows.

That’s why I’ve build this package!

Read HRV report file

read_HRV_reports() read and transform LabChart’s HRV report file (.txt) to a tidy tibble.

The first argument (file) is a path to either single HRV report file or folder containing multiple HRV report file, the latter case should be more useful to you.

# Path to a folder containing example HRV report text files
path_hrv <- labChartHRV_example("HRV")
path_hrv
#> [1] "/home/runner/work/_temp/Library/labChartHRV/extdata/HRV"

There are 4 HRV report .txt files in this folder.

dir(path_hrv)
#> [1] "file1.txt" "file2.txt" "file3.txt" "file4.txt"

Now, just supply the path to the folder to import it.

# Read In
hrv_tbl <- read_HRV_reports(path_hrv)
hrv_tbl
#> # A tibble: 4 × 41
#>   doc_id    File_LabChart Channel   Date  Start_time End_time Name  Gender   Age
#>   <chr>     <chr>         <fct>     <chr> <chr>      <chr>    <chr> <fct>  <int>
#> 1 file1.txt file1         Channel 2 16/2… 16/2/2563… 16/2/25… John  Male      60
#> 2 file2.txt file2         Channel 2 26/3… 26/3/2563… 26/3/25… Max   Male      56
#> 3 file3.txt file3         Channel 2 19/8… 19/8/2563… 19/8/25… Mary  Female    65
#> 4 file4.txt file4         Channel 2 10/9… 19/10/256… 19/10/2… Tom   Female    63
#> # … with 32 more variables: Beats_tot <dbl>, Rec_length <dbl>,
#> #   Class_bound <chr>, Discontinuities <dbl>, Beats_inserted <dbl>,
#> #   Beats_deleted <dbl>, NN_max <dbl>, NN_min <dbl>, NN_range <dbl>,
#> #   NN_mean <dbl>, NN_median <dbl>, HR_avg <dbl>, SDNN <dbl>, SD_del_NN <dbl>,
#> #   RMSSD <dbl>, Normals_count <dbl>, Ectopics_count <dbl>,
#> #   Artifacts_count <dbl>, NN50_count <dbl>, NN50_percent <dbl>,
#> #   Spec_intv <dbl>, Spec_mean_NN <dbl>, Power_tot <dbl>, VLF_freq <chr>, …

(Note: Internally read_HRV_reports() use readtext::readtext() to read textual data. I’ve set the text encoding to UTF-16LE. If you found that the output looks abnormal try changing text encoding via argument encoding.)

hrv_tbl has 41 columns and 4 rows. Column names correspond to each fields of the HRV report, and each rows correspond to each HRV report files.

# Column Names
names(hrv_tbl)
#>  [1] "doc_id"          "File_LabChart"   "Channel"         "Date"           
#>  [5] "Start_time"      "End_time"        "Name"            "Gender"         
#>  [9] "Age"             "Beats_tot"       "Rec_length"      "Class_bound"    
#> [13] "Discontinuities" "Beats_inserted"  "Beats_deleted"   "NN_max"         
#> [17] "NN_min"          "NN_range"        "NN_mean"         "NN_median"      
#> [21] "HR_avg"          "SDNN"            "SD_del_NN"       "RMSSD"          
#> [25] "Normals_count"   "Ectopics_count"  "Artifacts_count" "NN50_count"     
#> [29] "NN50_percent"    "Spec_intv"       "Spec_mean_NN"    "Power_tot"      
#> [33] "VLF_freq"        "VLF"             "LF_freq"         "LF"             
#> [37] "LF_nu"           "HF_freq"         "HF"              "HF_nu"          
#> [41] "LF_HF"

The description of each columns is stored in HRV_vars_desc data frame.

HRV_vars_desc
#> # A tibble: 41 × 2
#>    variable      description                       
#>    <chr>         <chr>                             
#>  1 doc_id        File name of the input HRV reports
#>  2 File_LabChart LabChart file name                
#>  3 Channel       Channel                           
#>  4 Date          Date                              
#>  5 Start_time    Start time                        
#>  6 End_time      End time                          
#>  7 Name          Name                              
#>  8 Gender        Gender                            
#>  9 Age           Age                               
#> 10 Beats_tot     Total number of beats             
#> # … with 31 more rows

Parse HRV report

parse_HRV_reports() is a lower-level function that parse HRV report from character vector to a data frame.

Read Manually

First, you need to read HRV report in to character vector using any text reading engine of your choice.

# Path to an HRV report text file
path_hrv1 <- labChartHRV_example("HRV/file1.txt")

# Read into character vector, I use `{readtext}`
hrv_chr <- readtext::readtext(path_hrv1, 
                              encoding = "UTF-16LE")$text
# For nice printing
glue::as_glue(hrv_chr) 
#> File: "file1"  Channel: Channel 2     Date: 16/2/2563 14:32:07.169
#> Start time: 16/2/2563 13:30:45.811    End time: 16/2/2563 13:45:46.061 
#> Name: John    Gender: Male    Age: 60 
#> Total number of beats = 485 (484 valid intervals, ectopics excluded)     Length of recording = 300.250 s
#> Classification boundaries: Artifact < 5 <= Ectopic < 179.364 <= Normal <= 1000 < Ectopic <= 2000 < Artifact
#> Discontinuities = 0    Manually inserted beats = 0    Manually deleted beats = 0
#> Maximum NN = 642.492 ms    Minimum NN = 192.683 ms    Range = 449.81 ms
#> Mean NN = 619.058 ms    Median NN = 621.648 ms    Average heart rate = 96.9215 BPM
#> SDNN = 23.1491 ms    SD of delta NN = 24.4761 ms    Ratio = 0.945783    RMSSD = 24.4508
#> Normals = 484 (100%)    Ectopics = 0 (0%)    Artifacts = 0 (0%)    NN50 = 3 (0.619835%)
#> Spectrum intervals = 484   Mean spectrum NN = 619.058 ms
#> Total power = 692.124 ms²    VLF (DC-0.04Hz) = 114.5 ms²
#> LF (0.04-0.15Hz) = 153.873 ms² (26.639 nu)     HF (0.15-0.4Hz) = 255.602 ms² (44.2506 nu)    LF/HF = 0.602002

Parse to Data Frame

Now parse the character vector to a data frame.

parse_HRV_reports(hrv_chr)
#> # A tibble: 1 × 40
#>   File_LabChart Channel   Date  Start_time End_time Name  Gender   Age Beats_tot
#>   <chr>         <fct>     <chr> <chr>      <chr>    <chr> <fct>  <int>     <dbl>
#> 1 file1         Channel 2 16/2… 16/2/2563… 16/2/25… John  Male      60       485
#> # … with 31 more variables: Rec_length <dbl>, Class_bound <chr>,
#> #   Discontinuities <dbl>, Beats_inserted <dbl>, Beats_deleted <dbl>,
#> #   NN_max <dbl>, NN_min <dbl>, NN_range <dbl>, NN_mean <dbl>, NN_median <dbl>,
#> #   HR_avg <dbl>, SDNN <dbl>, SD_del_NN <dbl>, RMSSD <dbl>,
#> #   Normals_count <dbl>, Ectopics_count <dbl>, Artifacts_count <dbl>,
#> #   NN50_count <dbl>, NN50_percent <dbl>, Spec_intv <dbl>, Spec_mean_NN <dbl>,
#> #   Power_tot <dbl>, VLF_freq <chr>, VLF <dbl>, LF_freq <chr>, LF <dbl>, …

Since I’ve import only 1 HRV report into a character vector of length 1, the resulting data frame has only 1 row.

However, you can supply HRV report character vector which has > 1 length, and the resulting data frame would have multiple rows corresponding to each HRV reports.

Selection Helper

labChartHRV comes with a helper for select HRV time-and frequency-domain variables.

HRV_vars_domain is a list with 2 elements:

  • time: contains character vector of time-domain variables.

  • freq: contains character vector of frequency-domain variables.

For example

vars <- HRV_vars_domain
str(vars)
#> List of 2
#>  $ time: chr [1:6] "SDNN" "SD_del_NN" "RMSSD" "Normals_count" ...
#>  $ freq: chr [1:10] "Power_tot" "VLF_freq" "VLF" "LF_freq" ...

Select HRV time-domain variables.

hrv_tbl %>% 
  select(Name, vars$time)
#> # A tibble: 4 × 7
#>   Name   SDNN SD_del_NN RMSSD Normals_count NN50_count NN50_percent
#>   <chr> <dbl>     <dbl> <dbl>         <dbl>      <dbl>        <dbl>
#> 1 John   23.1     24.5  24.5            484          3        0.620
#> 2 Max    31.0     14.2  14.2            400          2        0.5  
#> 3 Mary   17.1      5.58  5.58           420          0        0    
#> 4 Tom    22.2      6.20  6.19           434          1        0.230

Last updated: 2022-06-08