Skip to main content

5. 7 Summarizing with reduce

 Summarizing with reduce   Understanding Reduce Purpose of Reduce : reduce is a higher-order function used to compute a single value from an array. It's instrumental in operations like summing up numbers or finding an item in an array that meets a specific criterion (e.g., the script with the most characters). Operation : It works by repeatedly taking an element from the array and combining it with a current value until all elements have been processed. This process is akin to folding or reducing the array into a single value. 🎨: Think of reduce like making juice from oranges. You start with a bunch of oranges (the array), and then you squeeze them one by one into a jug (the single value). Your hands (the combining function) do the squeezing, and you might already have some juice in the jug to start with (the start value). 👩‍🎓: The Mechanics of reduce - The reduce function takes three arguments: the array to reduce, a combining function, and a starting value. The combin...

Chapter 4.7 Computing correlation

Computing correlation


 

👩‍🎓: Concept of Correlation: Correlation helps us understand if there is a relationship between two things. Here, we are looking at two questions:

  1. Did Jacques turn into a squirrel?
  2. Did Jacques eat pizza?

We want to know if these two events are related. For example, does eating pizza tend to happen on the same days that Jacques turns into a squirrel?

📚: Creating a Frequency Table: We track the number of days each combination of events occurs:

  • Days with no pizza and no squirrel transformation.
  • Days with pizza but no squirrel transformation.
  • Days with a squirrel transformation but no pizza.
  • Days with both pizza and a squirrel transformation.

🔍: Representing Combinations with Binary Numbers: Each combination is like a yes (1) or no (0) question:

  • 1st bit (left): Did Jacques turn into a squirrel? (Yes = 1, No = 0)
  • 2nd bit (right): Did Jacques eat pizza? (Yes = 1, No = 0)

So, we have four combinations: 00, 01, 10, 11. These binary numbers can also be represented in decimal as 0, 1, 2, 3, respectively.

🎨: Using an Array to Store Frequencies: We use an array with four elements to store how many times each combination happened:

  • table[0] for 00: No squirrel, no pizza.
  • table[1] for 01: No squirrel, but pizza.
  • table[2] for 10: Squirrel, but no pizza.
  • table[3] for 11: Squirrel and pizza.

🔬: The Phi Function: The phi function takes our array and calculates the correlation. It uses the formula for the Phi Coefficient to see if there's a pattern between the squirrel transformations and eating pizza.

For detailed explanation of the formula used to compute the correlation see the annotation of the previous section. 4.6.  The lycanthrope’s log

https://eloquentjavascript-annotated.blogspot.com/2024/01/chapter-46.html

 

What is the Phi Function?

The phi function is designed to calculate the phi coefficient (ϕ), a measure of correlation between two binary (true/false) variables. This coefficient tells us how strongly two binary variables are related to each other.

Understanding the Phi Coefficient

  • The phi coefficient ranges from -1 to 1.
  • A coefficient close to 0 suggests no correlation.
  • A coefficient close to 1 or -1 indicates a strong positive or negative correlation, respectively.

The phi Function

 function phi(table) {
  return (table[3] * table[0] - table[2] * table[1]) /
    Math.sqrt((table[2] + table[3]) *
              (table[0] + table[1]) *
              (table[1] + table[3]) *
              (table[0] + table[2]));
}

Breaking Down the Function

  1. Input: The phi function takes an array table as input. This array represents a 2x2 contingency table in a flattened form. The indices of the array represent the following frequencies:

    • table[0]: Both events are false (n00).
    • table[1]: First event is false, second is true (n01).
    • table[2]: First event is true, second is false (n10).
    • table[3]: Both events are true (n11).
  2. Formula: The function computes the phi coefficient using the formula:

 ϕ = (n11 * n00 - n10 * n01) / sqrt((n10 + n11) * (n00 + n01) * (n01 + n11) * (n00 + n10))

This formula calculates the correlation based on how often both events occur together compared to how often they occur separately.

Components:

Numerator: (table[3] * table[0] - table[2] * table[1]) calculates the difference between the product of the frequencies of both events being true and both being false, and the product of the frequencies of one event being true while the other is false. 

Actually there are 3 cases.

Positive: Intuitively  when both are true and both are false together has a great number than the number of opposites (one exist the other does not and vice versa) the positive correlation would exist.  When joint occurrences are significantly more frequent, it indicates a positive correlation, suggesting that the events tend to occur together.

Negative: When the negative cases one exists the other does not exist and  vice versa are of a great number then the negative correlation would exist. Conversely, when independent occurrences are more frequent, it suggests a negative correlation, indicating that the events tend to occur oppositely.

No correlation: Everything cancels out, everything is equally probable, all the four possible events will be equally probable.  That would mean everything would be equally probable and everything should cancel out to zero or close to 0. When both joint and independent occurrences are equally probable, there's no correlation, indicating that the events are unrelated.

Denominator: The square root term calculates the square root of the product of the sums of each event occurring and not occurring. (Without understanding the formula from the previous section 4.6 this part of the code does not make any sense. This part has the job of normalizing between -1 and 1). As everything is counted twice that is why the square root is necessary. I see the denominator as all possible events. The denominator, the square root of the product of the sums of each event occurring and not occurring, plays a crucial role in normalizing the correlation coefficient between -1 and 1. The square root accounts for the double counting of occurrences.

Example Usage

 console.log(phi([76, 9, 4, 1]));
// → 0.068599434

What This Does

  • This code calculates the phi coefficient for the given array [76, 9, 4, 1].
  • The array represents a specific set of frequencies for two binary events.
  • The result 0.068599434 indicates a very weak positive correlation between these two events.

Summary

The phi function is a practical implementation of a statistical formula to measure the correlation between two binary variables. It's useful in situations where you want to understand the relationship between two occurrences, such as whether one event is likely to happen when another event does. The provided example demonstrates its usage with a specific set of data, resulting in a calculation of a weak positive correlation.

 

 

        👩‍🎓: Extracting Data for Correlation Analysis:

  1. Data Collection: Jacques has kept a journal for three months, noting daily events and whether he transformed into a squirrel. This data is stored in a structured format, which in the JavaScript code is referred to as the JOURNAL.

  2. Creating a Frequency Table: The function tableFor is designed to create a frequency table for any event relative to Jacques' transformations. The table is represented as an array of four numbers, each representing a count of occurrences for different scenarios.

     

    📚: Function Breakdown:

    
    function tableFor(event, journal) {
      let table = [0, 0, 0, 0]; // Step 1: Initialize the frequency table with zeros.
      for (let i = 0; i < journal.length; i++) { // Step 2: Loop through all journal entries.
        let entry = journal[i], index = 0;
        if (entry.events.includes(event)) index += 1; // Step 3: Check if the day's events include the specific event.
        if (entry.squirrel) index += 2; // Step 4: Check if Jacques turned into a squirrel.
        table[index] += 1; // Step 5: Tally the occurrence in the frequency table.
      }
      return table; // Step 6: Return the completed frequency table.
    }
    • Step 1: The table starts with all counts set to zero: [0, 0, 0, 0].
    • Step 2: The function loops (for loop) through each day's entry in the journal.
    • Step 3: If the day's events include the event we're looking at (like "pizza"), we prepare to record that by setting the index to 1.
    • Step 4: If there was a squirrel transformation, we add 2 to the index. This gives us four possible outcomes:
      • 0: The event didn't occur, and there was no transformation.
      • 1: The event occurred, but there was no transformation.
      • 2: The event didn't occur, but there was a transformation.
      • 3: Both the event occurred and there was a transformation.
    • Step 5: We then increment the count for the corresponding scenario in our frequency table.
    • Step 6: Once all entries are checked, the function returns the frequency table.

    🎨: Understanding the Index Calculation: The index variable determines which position in the frequency table to update. It's calculated based on whether the specific event occurred and whether Jacques transformed into a squirrel. The index is incremented appropriately so that the resulting value maps to the correct cell in our frequency table.

    💡: Frequency Table Cells:

  3. table[0]: Incremented when neither the event nor the transformation occurred.
  4. table[1]: Incremented when the event occurred without the transformation.
  5. table[2]: Incremented when the transformation occurred without the event.
  6. table[3]: Incremented when both the event and the transformation occurred.

🔬: Using the Frequency Table: When we call tableFor("pizza", JOURNAL), we get the frequency table for the event "pizza". The resulting array [76, 9, 4, 1] represents the counts for each of the four scenarios described above.

🔄: Computing Correlations: Now, we can use this frequency table to compute the correlation for "pizza" using the phi function previously discussed. By doing this for every event in Jacques' journal, he can identify which events have a significant correlation with his transformations.

🎨: Visualizing the Process: Imagine Jacques' journal as a big spreadsheet. For each day, there's a row with a list of events and a column that marks if he turned into a squirrel. The tableFor function scans through each row and notes down the occurrences in a smaller table — our frequency table — specifically for the event we're interested in, like "pizza". Once we have that smaller table, it's like looking at a focused snapshot that tells us how often "pizza days" were also "squirrel days".

🔄: Conclusion: This systematic process allows Jacques to compute individual correlations and scrutinize them to see if any event consistently coincides with his transformations. If a particular event stands out with a high or low ϕ value, it might be a significant factor in his lycanthropy.

 

Link to the chapter in the book Eloquent Javascript:

Comments