Comprehensive Study Notes on R Programming: Data Types, Operators, and Control Structures

R Data Structures Overview

  • Core Concepts and Object Model:

    • Data structures are the foundational objects manipulated on a day-to-day basis in R programming.

    • Dealing with object conversions represents the most common source of despair for beginners.

    • Everything in R is an object.

    • R includes several essential data structures: Atomic vectors, Lists, Arrays, Matrices, Data Frames, Factors, and Vectors.

  • Primary Data Structure Definitions:

    • Vector: A collection of elements that is most commonly of mode character, integer, logical, or numeric. Vectors are divided into two main categories: atomic vectors and lists.

    • List: A specialized type of vector in which each element can be of a different type. In R, a list serves as a container and is not restricted to a single mode. It contains a heterogeneous mixture of data types and is also referred to as a generic vector because its elements can be any type of R object.

    • Array: A collection of data of a similar data type stored with contiguous memory allocation.

    • Matrix / Matrices: A two-dimensional R object in which elements are arranged in a rectangular layout. A matrix contains elements belonging exclusively to the same atomic type.

    • Data Frame: A two-dimensional array-like structure or tabular structure in which each column contains the values of one variable, and each row contains a set of values across each column.

    • Factors: Data objects utilized to categorize data and store it as distinct levels. Factors are capable of storing both character strings and integers.

Fundamental R Data Types

  • Data Type Specifications:

    • Data types specify the exact kind of data that can be stored within a variable.

    • Selecting the correct data type is essential for effective memory consumption and precise computational accuracy.

    • R does not require variables to be explicitly declared with a particular data type; variables can dynamically change type after assignment.

    • Each R data type possesses distinct properties and corresponding operations.


R Data Types Branch Diagram
  • Data Types and Characteristics:

    • Logical:

      • Description: A specialized data type reserved for data having only two possible values, construed as true or false.

      • Examples: True, False

    • Numeric:

      • Description: Any decimal value is classified as numeric in R; it constitutes the default computational data type.

      • Examples: 12, 32, 112, 5432

    • Integer:

      • Description: Whole numbers explicitly suffixed with an L flag, which instructs R to store the value as an integer.

      • Examples: 3L, 66L, 2346L

    • Complex:

      • Description: Values defined via pure imaginary numbers using the notation i.

      • Examples: Z=1+2i, t=7+3i

    • Character:

      • Description: Represents string values. Other objects are converted into character values using the as.character() function.

      • Examples: 'a', '"good"', "TRUE", '35.4'

    • Raw:

      • Description: A data type designed specifically to hold raw bytes of data.

Variables in R Programming

  • Definition and Architecture:

    • A variable is an allocated block of memory reserved for the storage of specific data, where the identifier associated with the variable is used to navigate and access that memory block.

    • The identifier assigned to a variable is known as its variable name.

    • Generally, an individual variable stores values corresponding to a single data type at any given time.

    • The term "variable" signifies that the stored data is subject to change during program execution and varies from time to time.

    • R is a dynamically typed programming language; variables are not declared with a fixed data type, but instead assume the data type of the R-object assigned to them.

  • Variable Creation and Assignment Operators:

    • R supports three distinct assignment methods:

      • Equal Operator (=): Assigns values using standard equality syntax: variable_name = value

      • Leftward Operator (<-): Copies data from right to left: variable_name <- value

      • Rightward Operator (->): Copies data from left to right: value -> variable_name

  • Naming Rules for Variables:

    • A valid variable name must be composed exclusively of letters, numbers, the dot (.), and the underscore (_) character (e.g., var.1_ is valid).

    • Except for the dot (.) and underscore (_), no special characters are permitted (e.g., var1 and var#1 are invalid).

    • A variable can begin with a letter or a dot (e.g., .var and var are valid).

    • A variable must never start with a number or an underscore (e.g., 2var and _var are invalid).

    • If a variable name begins with a dot (.), the immediately following character cannot be a number (e.g., .3var is invalid).

    • A variable name cannot be a reserved keyword in R (e.g., TRUE, FALSE).

  • Built-in Variable Management Methods:

    • class() Function:

      • Determines the data type of the variable passed as an argument.

      • Syntax: class(variable)

      • Example: r a = "hello" print(class(a)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • ls() Function:

      • Lists all variables currently stored in the workspace environment, which helps manage large environments and prevent accidental overwriting.

      • Syntax: ls()

      • Example: r a = "hello" b <- "hello" "hello" -> c print(ls()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • rm() Function:

      • Deletes an unwanted variable from the active workspace, freeing allocated memory.

      • Syntax: rm(variable)

      • Example: r a = "hello" rm(a) print(a) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Variable Scope:

    • Global Variables: Exist throughout the entire execution lifetime of a program. They are declared outside of all functions or code blocks and can be accessed or modified from any location in the code.

    • Local Variables: Exist only within the specific block or function in which they are declared. They cease to exist outside that block and cannot be accessed or manipulated externally.

  • Outputting Variables:

    • Variables can be outputted directly by typing their name in the console: r a <- "Hello" a &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • The print() function can be used explicitly: r a <- "Hello" print(a) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • When working within compound R expressions (such as blocks enclosed by curly braces {}), explicit invocation of print() is necessary to produce visible output: r for (x in 1:10) { print(x) } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

Operators in R

  • Overview of Operators:

    • An operator is a symbol that represents an operation, commanding the compiler to execute specific mathematical, logical, or relational manipulations on operands.

    • Operands can include complex numbers, integers, and numeric values.

    • Advanced operations in R encompass special operators for model formulas and list indexing.

  • Assignment Operators:

    • Used to assign new values to variables and vectors.

    • Left Assignment: <-, <<-, =

    • Right Assignment: ->, ->>

    • Assignments can be reversed directionally (e.g., x <- 3 is functionally identical to 3 -> x).

  • Arithmetic Operators:

    • Perform element-by-element arithmetic operations across vectors.

    • + : Addition (Example: x + y)

    • - : Subtraction (Example: x - y)

    • * : Multiplication (Example: x * y)

    • / : Division (Example: x / y)

    • ^ : Exponentiation (Example: x ^ y)

    • %% : Modulus / Remainder from division (Example: x %% y)

    • %/% : Integer Division (Example: x %/% y)

  • Relational Operators:

    • Define relations and test numerical equalities or inequalities.

    • Compares each element of the first vector to the corresponding element of the second vector, returning a boolean value (TRUE or FALSE).

    • == : Equal (Example: x == y)

    • != : Not equal (Example: x != y)

    • > : Greater than (Example: x > y)

    • < : Less than (Example: x < y)

    • >= : Greater than or equal to (Example: x >= y)

    • <= : Less than or equal to (Example: x <= y)

  • Logical Operators:

    • Combine conditional expressions and simulate element-wise logical evaluations returning boolean results.

    • Any non-zero integer, real number, or complex number is treated as TRUE.

    • & : Element-wise Logical AND operator; returns TRUE if both corresponding elements are TRUE.

    • && : Logical AND operator; evaluates only the first element of vectors and returns TRUE if both conditions are met.

    • | : Element-wise Logical OR operator; returns TRUE if at least one corresponding element is TRUE.

    • || : Logical OR operator; evaluates only the first element of vectors and returns TRUE if at least one condition is met.

    • ! : Logical NOT; returns FALSE if the statement is TRUE, and TRUE if the statement is FALSE.

  • Miscellaneous Operators:

    • Special-purpose operators used for sequence generation and matrix algebra rather than general computation.

    • : : Colon operator; generates a sequence of numbers in order (e.g., x <- 1:10).

    • %in% : Membership operator; evaluates whether an element belongs to a specified vector (e.g., x %in% y).

    • %*% : Matrix multiplication operator; performs matrix multiplication between compatible matrices (e.g., x <- Matrix1 %*% Matrix2).

User Input and Data Conversion

  • Input Acquisition Methods:

    • readline(): Accepts user input from the console strictly as a character string. For example, entering 255 stores the string "255".

    • scan(): Alternative method for reading data directly into vectors or lists.

  • Type Casting and Conversion Functions:

    • as.integer(x): Converts a character object x into an integer.

    • as.numeric(x): Converts character values into numeric data types (floats, doubles).

    • as.complex(n): Converts a value into a complex number format (e.g., 3+2i).

    • as.Date(x, format): Converts a string variable into an R Date object based on a provided format string (e.g., format "%m/%d/%y").

Vectors: Creation, Indexing, and Manipulation

  • Vector Basics:

    • A vector is a basic data structure representing a one-dimensional array where all components share identical data types.

    • Vectors serve the same function as arrays in other languages.

    • Components are the individual elements stored inside a vector.

    • Vector indexing in R begins at index 1, not 0.

  • Vector Creation:

    • Created using the combine/concatenate function c(): r A <- c(61, 4, 21, 67, 89, 2) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Vector Types:

    • Numeric Vectors: Contain numerical values including floats and integers: r A <- c(1, 2, 3, 4) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Character Vectors: Contain alphanumeric characters, strings, and symbols: r A <- c('Hi', '2', 'hello', 57) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Logical Vectors: Contain boolean constants (TRUE, FALSE) and missing values (NA): r A <- c(TRUE, FALSE, TRUE, NA) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Vector Length:

    • Determined using the length() function: r x <- c(1, 2, 3, 4, 5) length(x) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r fruits <- c("banana", "apple", "orange") length(fruits) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Accessing Vector Elements:

    • Single Element Access: Using the bracket operator []: r A <- c(2, 3, 1, 6, 8) cat('Using indexing operator', A[2], ' ') &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Multiple Element Access: Passing a vector of indices via c(): r B <- c(4, 8, 2, 1, 17) cat('Using combine function', B[c(4, 1)], ' ') &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Negative Indexing: Supplying negative index values excludes/drops the specified elements from the output: r t <- c("Sun", "Mon", "Tue", "Wed", "Thurs", "Fri", "Sat") x <- t[c(-2, -5)] print(x) # Output: [1] "Sun" "Tue" "Wed" "Fri" "Sat" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Modifying, Deleting, and Sorting Vectors:

    • Modifying Vector Elements: r X <- c(2, 7, 9, 7, 8, 2) X[3] <- 1 X[2] <- 9 cat('subscript operator', X, ' ') X[1:5] <- 0 cat('Logical indexing', X, ' ') X <- X[c(3, 2, 1)] cat('combine() function', X) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Deleting a Vector: Achieved by assigning NULL to the vector variable: r M <- c(8, 10, 2, 5) M <- NULL cat('Output vector', M) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Sorting Vector Elements: Accomplished with the sort() function: r X <- c(8, 2, 7, 1, 11, 2) A <- sort(X) # Ascending order cat('ascending order', A, ' ') B <- sort(X, decreasing = TRUE) # Descending order cat('descending order', B) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Identifying Vector Type: Checked using typeof(): r X <- c(8, 2, 7, 1, 11, 2) typeof(X) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


Vector Operations Diagram
  • Comprehensive Vector Operations:

    • Vector operations encompass element-wise addition, subtraction, multiplication, and division between vectors.

    • Major techniques include combining vectors, applying arithmetic operations, utilizing logical index vectors, numeric indexing, duplicate indexing, range indexes, out-of-order indexing, and referencing named vector members.

Lists: Creation, Access, and Modification

  • List Characteristics:

    • A list is a one-dimensional, heterogeneous data structure composed of an ordered collection of objects.

    • A list can store disparate data types within the same instance, including scalars, vectors, matrices, and functions.

    • List indexing starts at 1.

  • List Creation:

    • Constructed using the list() function: r list1 <- list(c(2, 5, 3), 21.3, sin) print(list1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Naming List Elements:

    • Naming list components improves code readability and simplifies access: r my_named_list <- list(name = "Sudheer", age = 25, city = "Delhi") print(my_named_list) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Accessing Components:

    • Access by Name: Components can be extracted using the dollar sign () operator: r empId = c(1, 2, 3, 4) empName = c("Debi", "Sandeep", "Subham", "Shiba") numberOfEmp = 4 empList = list( "ID" = empId, "Names" = empName, "Total Staff" = numberOfEmp ) print(empList) cat("Accessing name components using $ command ") print(empList$Names) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Access by Index:

      • Top-Level Components: Extracted using double square brackets [[ ]].

      • Inner-Level Components: Extracted by chaining single brackets [ ] onto double brackets [[ ]]. ```r

      Access second top-level component (Names)

      print(empList[[2]])

      Access second element of the second component ("Sandeep")

      print(empList[[2]][2])

      Access fourth element of the first component (4 from ID)

      print(empList[[1]][4])         ```

  • Modifying Lists:

    • List elements are updated or expanded by reassigning values via names or indices: r empList$`Total Staff` = 5 empList[[1]][5] = 5 empList[[2]][5] = "Kamala" print(empList) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • Concatenating Lists:

    • Multiple lists or elements can be merged using the concatenate operator c(): r empAge = c(34, 23, 18, 45) empList = c(empName, empAge) print(empList) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

Control Structures: Decision Making

  • Decision-Making Architecture:

    • Decision structures require specifying one or more logical conditions to evaluate.

    • When a condition evaluates to true, designated statements execute; if false, alternative branches execute or are bypassed.


General Decision Making Flowchart
  • The if Statement:

    • Consists of a boolean expression followed by an executable statement block.

    • Syntax: r if(boolean_expression) { # statement(s) will execute if the boolean expression is true. } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • Example: r if(is.integer(x)) { print("X is an Integer") } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • The if...else Statement:

    • Follows the initial if statement with an optional else block executed when the condition evaluates to false.


If-Else Flowchart
*   *Syntax*:
    ```r
    if(boolean_expression) {
        # statement(s) will execute if the boolean expression is true.
    } else {
        # statement(s) will execute if the boolean expression is false.
    }

         * *Example*: r x <- c("what", "is", "truth") if("Truth" %in% x){ print("Truth is found") } else { print("Truth is not found") }         ```

  • The if...else if...else Statement:

    • Enables testing multiple conditional branches sequentially.

    • Structural constraints:

      • An if statement can include zero or one else block, which must appear after all else if statements.

      • An if statement can contain zero to multiple else if blocks, which must precede the else block.

      • Once any else if branch succeeds, none of the remaining else if or else blocks will be tested.

    • Syntax: r if(boolean_expression 1) { # Executes when boolean expression 1 is true. } else if(boolean_expression 2) { # Executes when boolean expression 2 is true. } else if(boolean_expression 3) { # Executes when boolean expression 3 is true. } else { # Executes when none of the above conditions are true. } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

  • The switch Statement:

    • Tests an expression for equality against an enumerated list of case values.


Switch Statement Flowchart
*   *Syntax*:
    ```r
    switch(expression, case1, case2, case3)

        ```

Control Structures: Loops and Jump Statements

  • Loop Mechanisms:

    • While statements normally execute in sequential order, loops permit repeated execution of a code block based on evaluation criteria.


General Loop Structure
  • The while Loop:

    • Executes the target code block repeatedly as long as the specified test condition remains true.


While Loop Flowchart
*   *Syntax*:
    ```r
    while (condition) {
        # conditional code
    }

        ```

  • The for Loop:

    • A repetition control structure designed to execute a block of code a set number of times over elements of an iterable sequence.

    • Unlike many programming languages, R's for loops can iterate over non-numeric collections, including character vectors, logical vectors, lists, or expressions.


For Loop Flowchart
*   *Syntax*:
    ```r
    for (value in vector) {
        statements
    }

        ```

  • Loop Control Statements:

    • Alter normal sequential flow within loop scopes. When execution leaves a scope, any automatic objects created inside that scope are destroyed.

    • break Statement:

      • Immediately terminates the enclosing loop and redirects control to the statement directly following the loop.

      • Can also terminate cases in a switch construct.


      Break Statement Flowchart
      • Syntax: r break &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

    • next Statement:

      • Skips the remaining statements in the current iteration of the loop without terminating it, immediately starting the next iteration.


      Next Statement Flowchart
      • Syntax: r next &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

      • Example: r v <- LETTERS[1:6] for (i in v){ if (i == "D"){ next } print(i) } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;