LA Foundations badge

LASER Institute Foundation Learning Lab 1

Author

Nazim Karaca

Published

July 18, 2025

The final activity for each learning lab provides space to work with data and to reflect on how the concepts and techniques introduced in each lab might apply to your own research.

To earn a badge for each lab, you are required to respond to a set of prompts for two parts:

Part I: Reflect and Plan

Use the institutional library (e.g. NCSU Library), Google Scholar or search engine to locate a research article, presentation, or resource that applies learning analytics analysis to an educational context or topic of interest. More specifically, locate a study that makes use of one of the data structures we learned today. You are also welcome to select one of your research papers.

  1. Provide an APA citation for your selected study.

    • Renò, V., Stella, E., Patruno, C., Capurso, A., Dimauro, G., & Maglietta, R. (2022). Learning Analytics: Analysis of Methods for Online Assessment. Applied Sciences, 12(18), 9296. https://doi.org/10.3390/app12189296
  2. What types of data are associated with LA ?

    • Interactions between instructors and students

    • Administrative data

    • Demographic data

    • Student affectivity

    • Specifically, these data types are found in most LA data:

      • numbers (FLOAT or INT)

      • CHAR or strings

      • dates

      • Boolean (True or False)

      • Null, None or NA data

  3. What type of data structures are analyzed in the educational context?

    • Structured data
    • Unstructured data
    • Semi-structured data
    • Meta data
  4. How might this article be used to better understand a dataset or educational context of personal or professional interest to you?

    • We have a lot of CS1 data from prior semesters that we want to analyze for predictive values, and the article seems to confirm that Supervised statistical learning techniques have good predictive outcomes with this kind of data.
  5. Finally, how do these processes compare with what teachers and educational organizations already do to support and assess student learning?

    • I have very little experience in this, but I haven’t been shown any support that offers this kind of predictive possibility.

Draft a research question of guided by techniques and data sources that you are potentially interested in exploring in more depth.

  1. What data source(s) should be analyzed or discussed?

    • University of Delaware’s CS1 data from the prior years.
  2. What is the purpose of your article?

    • Discovering which subsets of assignments have the most predictive value for good student outcomes.
  3. Explain the analytical level at which these data would need to be collected and analyzed.

    • The data has all be collected, but the analysis is daunting due to the size and detail of the dataset, which doesn’t include any video, but is about 20 GB worth.
  4. How, if at all, will your article touch upon the application(s) of LA to “understand and improve learning and the contexts in which learning occurs?”

    • I’d like to help provide instructors with opportunities to identify the best opportunities to make in-class interventions to help the greatest number of struggling students to obtain the best overall outcomes in the course.

Part II: Data Product

In our Learning Analytics code-along, we scratched the surface on the number of ways that we can wrangle the data.

Using one of the data sets provided in the data folder, your goal for this lab is to extend the Learning Analytics Workflow from our code-along by preparing and wrangling different data.

Or alternatively, you may use your own data set to use in the workflow. If you do decide to use your own data set you must include:

  • Show two different ways using select function with your data, inspect and save as a new object.

  • Show one way to use filter function with your data, inspect and save as a new object.

  • Show one way using arrange function with your data, inspect and save as a new object.

  • Use the pipe operator to bring it all together.

Feel free to create a new script in your lab 2 to work through the following problems. Then when satisfied add the code in the code chunks below. Don’t forget to run the code to make sure it works.

Instructions:

  1. Add your name to the document in author.

  2. Set up the first (or, two if using an Introduction) phases of the LA workflow below. I’ve added the wrangle section for you. You will need to Prepare the libraries necessary to wrangle the data.

  3. In the chunk called read-data: Import the sci-online-classes.csv from the data folder and save as a new object called sci_classes. Then inspect your data using a function of your choice.

# Type your code here
#load todyverse
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.2     ✔ tibble    3.3.0
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
#import
sci_classes <- read_csv("data/sci-online-classes.csv")
Rows: 603 Columns: 30
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (6): course_id, subject, semester, section, Gradebook_Item, Gender
dbl (23): student_id, total_points_possible, total_points_earned, percentage...
lgl  (1): Grade_Category

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#inspect your data
view(sci_classes)
  1. In the select-1 code chunk: Use the ‘select’ function to select student_id, subject, semester, FinalGradeCEMS. Assign to a new object with a different name (you choose the name).
# Type your code here
selected_sci_classes <- select(sci_classes, student_id, subject, semester, FinalGradeCEMS)

#inspect your data
sorted_selected_SC <- selected_sci_classes %>% arrange(FinalGradeCEMS)
sorted_selected_SC
# A tibble: 603 × 4
   student_id subject semester FinalGradeCEMS
        <dbl> <chr>   <chr>             <dbl>
 1      90995 BioA    S116              0    
 2      92606 BioA    S216              0.535
 3      95684 FrScA   S216              0.903
 4      90996 OcnA    S216              1.80 
 5      94876 OcnA    S216              2.93 
 6      92633 BioA    S116              3.01 
 7      85390 PhysA   S116              3.06 
 8      94630 OcnA    S216              3.43 
 9      90995 AnPhA   S116              5.04 
10      96677 AnPhA   S216              5.2  
# ℹ 593 more rows

What do you notice about FinalGradeCEMS? (*Hint: NAs?)

  • Answer here: missing 30 values among the final grades. Unclear if that is an indication that the data was not entered, or if the students dropped the course. May affect analysis, but R tends to disregard null values adequately.
  1. In code chunk named select-2 select all columns except subject and section. Assign to a new object with a different name. Inspect your data frame with a different function.
# Type your code here
select2_sci_classes <- select(sci_classes, -subject, -section)

summary(select2_sci_classes)
   student_id     course_id         total_points_possible total_points_earned
 Min.   :43146   Length:603         Min.   :  840         Min.   :  651      
 1st Qu.:85612   Class :character   1st Qu.: 2810         1st Qu.: 2050      
 Median :88340   Mode  :character   Median : 3583         Median : 2757      
 Mean   :86070                      Mean   : 4274         Mean   : 3245      
 3rd Qu.:92730                      3rd Qu.: 5069         3rd Qu.: 3875      
 Max.   :97441                      Max.   :15552         Max.   :12208      
                                                                             
 percentage_earned   semester         Gradebook_Item     Grade_Category
 Min.   :0.3384    Length:603         Length:603         Mode:logical  
 1st Qu.:0.7047    Class :character   Class :character   NA's:603      
 Median :0.7770    Mode  :character   Mode  :character                 
 Mean   :0.7577                                                        
 3rd Qu.:0.8262                                                        
 Max.   :0.9106                                                        
                                                                       
 FinalGradeCEMS   Points_Possible  Points_Earned       Gender         
 Min.   :  0.00   Min.   :  5.00   Min.   :  0.00   Length:603        
 1st Qu.: 71.25   1st Qu.: 10.00   1st Qu.:  7.00   Class :character  
 Median : 84.57   Median : 10.00   Median : 10.00   Mode  :character  
 Mean   : 77.20   Mean   : 76.87   Mean   : 68.63                     
 3rd Qu.: 92.10   3rd Qu.: 30.00   3rd Qu.: 26.12                     
 Max.   :100.00   Max.   :935.00   Max.   :828.20                     
 NA's   :30                        NA's   :92                         
       q1              q2              q3              q4       
 Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
 1st Qu.:4.000   1st Qu.:3.000   1st Qu.:3.000   1st Qu.:4.000  
 Median :4.000   Median :4.000   Median :3.000   Median :4.000  
 Mean   :4.296   Mean   :3.629   Mean   :3.327   Mean   :4.268  
 3rd Qu.:5.000   3rd Qu.:4.000   3rd Qu.:4.000   3rd Qu.:5.000  
 Max.   :5.000   Max.   :5.000   Max.   :5.000   Max.   :5.000  
 NA's   :123     NA's   :126     NA's   :123     NA's   :125    
       q5              q6              q7              q8       
 Min.   :2.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
 1st Qu.:4.000   1st Qu.:4.000   1st Qu.:3.000   1st Qu.:4.000  
 Median :4.000   Median :4.000   Median :4.000   Median :4.000  
 Mean   :4.191   Mean   :4.008   Mean   :3.907   Mean   :4.289  
 3rd Qu.:5.000   3rd Qu.:5.000   3rd Qu.:4.750   3rd Qu.:5.000  
 Max.   :5.000   Max.   :5.000   Max.   :5.000   Max.   :5.000  
 NA's   :127     NA's   :127     NA's   :129     NA's   :129    
       q9             q10          TimeSpent       TimeSpent_hours   
 Min.   :1.000   Min.   :1.000   Min.   :   0.45   Min.   :  0.0075  
 1st Qu.:3.000   1st Qu.:4.000   1st Qu.: 851.90   1st Qu.: 14.1983  
 Median :4.000   Median :4.000   Median :1550.91   Median : 25.8485  
 Mean   :3.487   Mean   :4.101   Mean   :1799.75   Mean   : 29.9959  
 3rd Qu.:4.000   3rd Qu.:5.000   3rd Qu.:2426.09   3rd Qu.: 40.4348  
 Max.   :5.000   Max.   :5.000   Max.   :8870.88   Max.   :147.8481  
 NA's   :129     NA's   :129     NA's   :5         NA's   :5         
 TimeSpent_std          int              pc              uv       
 Min.   :-1.3280   Min.   :2.000   Min.   :1.500   Min.   :1.000  
 1st Qu.:-0.6996   1st Qu.:3.900   1st Qu.:3.000   1st Qu.:3.333  
 Median :-0.1837   Median :4.200   Median :3.500   Median :3.667  
 Mean   : 0.0000   Mean   :4.219   Mean   :3.608   Mean   :3.719  
 3rd Qu.: 0.4623   3rd Qu.:4.700   3rd Qu.:4.000   3rd Qu.:4.167  
 Max.   : 5.2188   Max.   :5.000   Max.   :5.000   Max.   :5.000  
 NA's   :5         NA's   :76      NA's   :75      NA's   :75     
  1. In the code chunk named filter-1, Filter the sci_classes data frame for students in OcnA courses. Assign to a new object with a different name. Use the head() function to examine your data frame.
#Type your code here
ocean_sci_classes <- sci_classes %>% filter(subject == "OcnA")

#inspect your data
head(ocean_sci_classes)
# A tibble: 6 × 30
  student_id course_id    total_points_possible total_points_earned
       <dbl> <chr>                        <dbl>               <dbl>
1      44638 OcnA-S116-01                  3531                2672
2      47979 OcnA-S216-01                  4562                3090
3      54066 OcnA-S116-01                  4641                3429
4      54282 OcnA-S116-02                  3581                2777
5      54342 OcnA-S116-02                  3256                2876
6      54346 OcnA-S116-01                  4471                3773
# ℹ 26 more variables: percentage_earned <dbl>, subject <chr>, semester <chr>,
#   section <chr>, Gradebook_Item <chr>, Grade_Category <lgl>,
#   FinalGradeCEMS <dbl>, Points_Possible <dbl>, Points_Earned <dbl>,
#   Gender <chr>, q1 <dbl>, q2 <dbl>, q3 <dbl>, q4 <dbl>, q5 <dbl>, q6 <dbl>,
#   q7 <dbl>, q8 <dbl>, q9 <dbl>, q10 <dbl>, TimeSpent <dbl>,
#   TimeSpent_hours <dbl>, TimeSpent_std <dbl>, int <dbl>, pc <dbl>, uv <dbl>

Q: How many rows does the head() function display? Hint: Check the dimensions of your tibble in the console.

  • Answer here: the head function displays 6 rows of data
  1. In code chunk named filter-2, filter the sci_classes data frame so rows with NA for points earned are removed. Assign to a new object with a different name. Use glimpse() to examine all columns of your data frame.
# Type your code here
earned_sci_classes <- sci_classes %>% filter(Points_Earned >= 0)

#inspect data 
glimpse(earned_sci_classes)
Rows: 511
Columns: 30
$ student_id            <dbl> 44638, 47979, 48797, 52446, 53447, 53475, 53475,…
$ course_id             <chr> "OcnA-S116-01", "OcnA-S216-01", "PhysA-S116-01",…
$ total_points_possible <dbl> 3531, 4562, 2207, 2086, 4655, 1710, 1209, 4641, …
$ total_points_earned   <dbl> 2672, 3090, 1910, 1719, 3149, 1402, 977, 3429, 2…
$ percentage_earned     <dbl> 0.7567261, 0.6773345, 0.8654282, 0.8240652, 0.67…
$ subject               <chr> "OcnA", "OcnA", "PhysA", "PhysA", "FrScA", "FrSc…
$ semester              <chr> "S116", "S216", "S116", "S116", "S116", "S116", …
$ section               <chr> "01", "01", "01", "01", "01", "02", "01", "01", …
$ Gradebook_Item        <chr> "ATTEMPTED", "POINTS EARNED & TOTAL COURSE POINT…
$ Grade_Category        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ FinalGradeCEMS        <dbl> 81.70184, 81.85260, 84.00000, 97.77778, 96.11872…
$ Points_Possible       <dbl> 10, 5, 438, 10, 443, 5, 12, 10, 5, 10, 220, 30, …
$ Points_Earned         <dbl> 10.00, 4.00, 399.00, 10.00, 425.00, 2.50, 12.00,…
$ Gender                <chr> "F", "M", "F", "F", "F", "M", "M", "M", "F", "F"…
$ q1                    <dbl> 4, 5, 4, 3, 4, NA, NA, 4, 3, 5, NA, 4, 4, NA, 4,…
$ q2                    <dbl> 4, 5, 3, 3, 3, NA, NA, 5, 3, 3, NA, 2, 4, NA, 3,…
$ q3                    <dbl> 3, 3, 3, 3, 3, NA, NA, 3, 3, 5, NA, 2, 3, NA, 3,…
$ q4                    <dbl> 4, 5, 4, 3, 4, NA, NA, 5, 3, 5, NA, 4, 5, NA, 4,…
$ q5                    <dbl> 4, 5, 4, 3, 4, NA, NA, 5, 4, 5, NA, 4, 4, NA, 4,…
$ q6                    <dbl> 4, 5, 4, 4, 3, NA, NA, 5, 3, 5, NA, 4, 4, NA, 3,…
$ q7                    <dbl> 4, 4, 4, 3, 3, NA, NA, 5, 3, 5, NA, 4, 5, NA, 3,…
$ q8                    <dbl> 5, 5, 4, 3, 4, NA, NA, 4, 3, 5, NA, 4, 4, NA, 4,…
$ q9                    <dbl> 4, 5, NA, 3, 2, NA, NA, 5, 2, 2, NA, 2, 4, NA, 2…
$ q10                   <dbl> 4, 5, 3, 3, 5, NA, NA, 4, 4, 5, NA, 4, 4, NA, 3,…
$ TimeSpent             <dbl> 1382.7001, 1598.6166, 1481.8000, 1390.2167, 1479…
$ TimeSpent_hours       <dbl> 23.04500167, 26.64361000, 24.69666667, 23.170278…
$ TimeSpent_std         <dbl> -0.30780313, -0.14844697, -0.23466291, -0.302255…
$ int                   <dbl> 4.2, 5.0, 3.8, 3.0, 4.2, NA, NA, 4.4, 3.4, 4.7, …
$ pc                    <dbl> 3.50, 3.50, 3.50, 3.00, 3.00, NA, NA, 4.00, 3.00…
$ uv                    <dbl> 4.000000, 5.000000, 3.500000, 3.333333, 2.666667…
  1. In the code chunk called arrange-1, Arrange sci_classes data by subject then percentage_earned in descending order. Assign to a new object. Use the str() function to examine the data type of each column in your data frame.
# Type your code here
arranged_sci_classes <- sci_classes %>% arrange(subject, desc(percentage_earned))

#inpsect data
str(arranged_sci_classes)
spc_tbl_ [603 × 30] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ student_id           : num [1:603] 70192 86488 96690 91175 86267 ...
 $ course_id            : chr [1:603] "AnPhA-S116-02" "AnPhA-S116-01" "AnPhA-S216-01" "AnPhA-S116-02" ...
 $ total_points_possible: num [1:603] 1936 3342 4804 3199 3045 ...
 $ total_points_earned  : num [1:603] 1763 3033 4309 2867 2705 ...
 $ percentage_earned    : num [1:603] 0.911 0.908 0.897 0.896 0.888 ...
 $ subject              : chr [1:603] "AnPhA" "AnPhA" "AnPhA" "AnPhA" ...
 $ semester             : chr [1:603] "S116" "S116" "S216" "S116" ...
 $ section              : chr [1:603] "02" "01" "01" "02" ...
 $ Gradebook_Item       : chr [1:603] "POINTS EARNED & TOTAL COURSE POINTS" "POINTS EARNED & TOTAL COURSE POINTS" "POINTS EARNED & TOTAL COURSE POINTS" "POINTS EARNED & TOTAL COURSE POINTS" ...
 $ Grade_Category       : logi [1:603] NA NA NA NA NA NA ...
 $ FinalGradeCEMS       : num [1:603] 96 87.4 64.8 82.2 35.1 ...
 $ Points_Possible      : num [1:603] 10 28 10 5 50 15 10 10 353 460 ...
 $ Points_Earned        : num [1:603] 7 26 3 5 50 11 8 10 330 452 ...
 $ Gender               : chr [1:603] "F" "M" "F" "F" ...
 $ q1                   : num [1:603] 4 4 4 5 5 4 5 4 NA NA ...
 $ q2                   : num [1:603] 3 4 3 3 5 2 4 4 NA NA ...
 $ q3                   : num [1:603] 3 2 2 3 3 3 4 3 NA NA ...
 $ q4                   : num [1:603] 4 3 5 5 5 4 5 4 NA NA ...
 $ q5                   : num [1:603] 4 3 4 5 5 4 5 4 NA NA ...
 $ q6                   : num [1:603] 3 3 4 4 5 3 5 4 NA NA ...
 $ q7                   : num [1:603] 3 3 3 3 4 4 5 4 NA NA ...
 $ q8                   : num [1:603] 5 2 4 5 5 4 4 4 NA NA ...
 $ q9                   : num [1:603] 2 3 3 3 5 1 4 4 NA NA ...
 $ q10                  : num [1:603] 5 3 2 5 5 2 5 4 NA NA ...
 $ TimeSpent            : num [1:603] 1537 3600 1970 1315 406 ...
 $ TimeSpent_hours      : num [1:603] 25.62 60 32.83 21.92 6.77 ...
 $ TimeSpent_std        : num [1:603] -0.194 1.328 0.125 -0.358 -1.029 ...
 $ int                  : num [1:603] 4.4 3 3.8 5 5 3.9 4.6 4 4.8 4.6 ...
 $ pc                   : num [1:603] 3 2.5 2.5 3 3.5 3.5 3.75 3.5 3.5 4.5 ...
 $ uv                   : num [1:603] 2.67 3.33 3.33 3.33 5 ...
 - attr(*, "spec")=
  .. cols(
  ..   student_id = col_double(),
  ..   course_id = col_character(),
  ..   total_points_possible = col_double(),
  ..   total_points_earned = col_double(),
  ..   percentage_earned = col_double(),
  ..   subject = col_character(),
  ..   semester = col_character(),
  ..   section = col_character(),
  ..   Gradebook_Item = col_character(),
  ..   Grade_Category = col_logical(),
  ..   FinalGradeCEMS = col_double(),
  ..   Points_Possible = col_double(),
  ..   Points_Earned = col_double(),
  ..   Gender = col_character(),
  ..   q1 = col_double(),
  ..   q2 = col_double(),
  ..   q3 = col_double(),
  ..   q4 = col_double(),
  ..   q5 = col_double(),
  ..   q6 = col_double(),
  ..   q7 = col_double(),
  ..   q8 = col_double(),
  ..   q9 = col_double(),
  ..   q10 = col_double(),
  ..   TimeSpent = col_double(),
  ..   TimeSpent_hours = col_double(),
  ..   TimeSpent_std = col_double(),
  ..   int = col_double(),
  ..   pc = col_double(),
  ..   uv = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
  1. In the code chunk name final-wrangle, use sci_classes data data and the %>% pipe operator:
  • Select student_id, subject, semester, FinalGradeCEMS.
  • Filter for students in OcnA courses.
  • Arrange grades by section in descending order.
  • Assign to a new object.
  • Examine the contents using a method of your choosing.
#Type your code here
# added section to make bullet point 3 possible
final_sci_classes <- select(sci_classes, student_id, subject, section, semester, FinalGradeCEMS) %>% 
  filter(subject == "OcnA") %>% 
  arrange(section, desc(FinalGradeCEMS))

#inspect data
tail(final_sci_classes)
# A tibble: 6 × 5
  student_id subject section semester FinalGradeCEMS
       <dbl> <chr>   <chr>   <chr>             <dbl>
1      95868 OcnA    02      S216              39.4 
2      94327 OcnA    02      S216              15.9 
3      87122 OcnA    02      S116               8.04
4      94876 OcnA    02      S216               2.93
5      85487 OcnA    02      S116              NA   
6      88307 OcnA    03      S116              54.5 

Render & Submit

Congratulations, you’ve completed Foundations Learning Badge 1!

To receive your the Foundations Badge, you will need to render this document and publish via a method designated by your instructor such as: Quarto Pub, Posit Cloud, RPubs , GitHub Pages, or other methods. Once you have shared a link to you published document with your instructor and they have reviewed your work, you will be provided a physical or digital version of the badge pictured at the top of this document!

If you have any questions about this badge, or run into any technical issues, don’t hesitate to contact your instructor. Once your instructor has checked your link, you will be provided a physical version of the badge!

Complete the following steps to submit your work for review:

  1. First, change the name of the author: in the YAML header at the very top of this document to your name. The YAML header controls the style and feel for knitted document but doesn’t actually display in the final output.

  2. Next, click the knit button in the toolbar above to “knit” your R Markdown document to a HTML file that will be saved in your R Project folder. You should see a formatted webpage appear in your Viewer tab in the lower right pan or in a new browser window. Let’s us know if you run into any issues with knitting.

  3. Finally, publish.