xbe.at

Data science

Exploring Python's Fundamental Data Types

9 min read, 13 sections

Contents
  1. Boolean Fundamentals
  2. Advanced Boolean Logic
  3. Integer Operations and Properties
  4. Advanced Integer Applications
  5. Float Precision and Mathematics
  6. Float Special Values and Scientific Notation
  7. Type Conversion and Numeric Systems
  8. Real-world Application: Financial Calculations
  9. Real-world Application: Data Analysis with Mixed Types
  10. Mathematical Operations with Mixed Types
  11. Type Conversion Edge Cases
  12. Advanced Real-world Application: Signal Processing
  13. Additional Resources

Boolean Fundamentals

Python's boolean type represents binary states True and False, forming the foundation of logical operations and control flow. Booleans enable comparison operations, conditional statements, and serve as flags for program state management.

# Basic boolean operations and comparisons
x, y = True, False

# Logical operators
print(f"AND operation: {x and y}")  # False
print(f"OR operation: {x or y}")    # True
print(f"NOT operation: {not x}")    # False

# Comparison operations producing booleans
num1, num2 = 10, 20
is_greater = num1 > num2
is_equal = num1 == num2

print(f"10 > 20: {is_greater}")    # False
print(f"10 == 20: {is_equal}")    # False

Advanced Boolean Logic

Boolean algebra in Python extends beyond simple comparisons, allowing complex logical expressions through compound statements and bitwise operations, essential for data validation and control structures.

# Complex boolean expressions and short-circuit evaluation
def is_valid_user(age, verified, permissions):
    return (age >= 18 and verified) or permissions.get('admin', False)

# Example usage
user_data = {'age': 25, 'verified': True}
admin_permissions = {'admin': True}
regular_permissions = {'user': True}

# Evaluating different scenarios
print(f"Valid adult user: {is_valid_user(25, True, regular_permissions)}")    # True
print(f"Valid admin: {is_valid_user(16, False, admin_permissions)}")         # True
print(f"Invalid user: {is_valid_user(16, False, regular_permissions)}")      # False

# Bitwise operations with booleans
a, b = True, False
print(f"Bitwise AND: {a & b}")    # False
print(f"Bitwise OR: {a | b}")     # True
print(f"Bitwise XOR: {a ^ b}")    # True

Integer Operations and Properties

Integers in Python are unbounded, allowing arbitrary-precision arithmetic without overflow concerns. They support a rich set of mathematical operations and serve as the foundation for numerical computations.

# Demonstrating integer operations and properties
# Basic arithmetic
a, b = 1234567890, 987654321
result = a * b
print(f"Large multiplication: {result}")

# Integer division and modulo
x, y = 17, 5
print(f"Integer division: {x // y}")    # 3
print(f"Modulo: {x % y}")              # 2
print(f"Divmod: {divmod(x, y)}")       # (3, 2)

# Bit manipulation
num = 42
print(f"Binary representation: {bin(num)}")          # 0b101010
print(f"Left shift by 2: {num << 2}")               # 168
print(f"Right shift by 1: {num >> 1}")              # 21
print(f"Bitwise complement: {~num}")                # -43

Advanced Integer Applications

# Advanced integer operations for cryptography and optimization
def prime_factors(n):
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n //= d
        d += 1
        if d * d > n:
            if n > 1:
                factors.append(n)
            break
    return factors

# Binary exponentiation for efficient power calculation
def fast_power(base, exponent, modulus=None):
    result = 1
    while exponent > 0:
        if exponent & 1:
            result = result * base if modulus is None else (result * base) % modulus
        base = base * base if modulus is None else (base * base) % modulus
        exponent >>= 1
    return result

# Example usage
number = 84
print(f"Prime factors of {number}: {prime_factors(number)}")
print(f"2^10 = {fast_power(2, 10)}")
print(f"2^10 mod 1000 = {fast_power(2, 10, 1000)}")

Float Precision and Mathematics

Floating-point numbers in Python follow IEEE-754 double-precision standard, providing approximately 15-17 decimal digits of precision. Understanding their behavior is crucial for scientific computing.

import math
import decimal
from decimal import Decimal

# Demonstrating float precision and limitations
a = 0.1 + 0.2
b = 0.3
print(f"0.1 + 0.2 == 0.3: {a == b}")  # False
print(f"Actual value of 0.1 + 0.2: {a}")

# Using decimal for precise calculations
decimal.getcontext().prec = 28
d1 = Decimal('0.1')
d2 = Decimal('0.2')
d3 = d1 + d2
print(f"Precise decimal calculation: {d3}")

# Mathematical operations
x = 3.14159
print(f"Floor: {math.floor(x)}")
print(f"Ceil: {math.ceil(x)}")
print(f"Round to 2 decimal places: {round(x, 2)}")

Float Special Values and Scientific Notation

Python's float type includes special values for handling exceptional cases in scientific computing. Understanding these values and scientific notation is crucial for numerical analysis and scientific calculations.

import math
import numpy as np

# Special float values and representations
inf_pos = float('inf')
inf_neg = float('-inf')
nan = float('nan')

# Scientific notation
scientific = 1.23e-4
print(f"Scientific notation: {scientific}")  # 0.000123

# Special value operations
print(f"Infinity check: {math.isinf(inf_pos)}")  # True
print(f"NaN check: {math.isnan(nan)}")          # True

# Float range and precision
epsilon = np.finfo(float).eps
print(f"Machine epsilon: {epsilon}")
print(f"Max float: {np.finfo(float).max}")
print(f"Min float: {np.finfo(float).min}")

# Handling division by zero
try:
    result = 1.0 / 0.0
    print(f"1.0/0.0 = {result}")  # inf
except ZeroDivisionError as e:
    print(f"Error: {e}")

Type Conversion and Numeric Systems

Understanding type conversion between numeric types is essential for precise calculations and data processing. Python provides built-in functions for seamless conversion between different number representations.

# Type conversion examples
integer_num = 42
float_num = 3.14159
bool_val = True

# Basic type conversions
print(f"Integer to float: {float(integer_num)}")
print(f"Float to integer: {int(float_num)}")
print(f"Boolean to integer: {int(bool_val)}")

# Number system conversions
decimal_num = 255
print(f"Decimal to binary: {bin(decimal_num)}")
print(f"Decimal to octal: {oct(decimal_num)}")
print(f"Decimal to hex: {hex(decimal_num)}")

# String to number conversions
print(f"Binary string to int: {int('11111111', 2)}")
print(f"Hex string to int: {int('FF', 16)}")
print(f"Octal string to int: {int('377', 8)}")

# Complex number conversion
complex_num = complex(3, 4)
print(f"Complex number: {complex_num}")
print(f"Complex magnitude: {abs(complex_num)}")

Real-world Application: Financial Calculations

Financial calculations require precise handling of decimal numbers to avoid rounding errors. This example demonstrates proper monetary calculations using the decimal module.

from decimal import Decimal, ROUND_HALF_UP
import pandas as pd

class FinancialCalculator:
    def __init__(self):
        self.context = decimal.getcontext()
        self.context.rounding = ROUND_HALF_UP
        self.context.prec = 6

    def compound_interest(self, principal, rate, years):
        """Calculate compound interest with precise decimal arithmetic"""
        p = Decimal(str(principal))
        r = Decimal(str(rate))
        t = Decimal(str(years))
        
        # Formula: A = P(1 + r)^t
        amount = p * (Decimal('1') + r) ** t
        return amount.quantize(Decimal('0.01'))

    def loan_payment(self, principal, rate, years):
        """Calculate monthly loan payment"""
        p = Decimal(str(principal))
        r = Decimal(str(rate / 12))  # Monthly rate
        n = Decimal(str(years * 12))  # Number of payments
        
        # Formula: PMT = P * (r * (1 + r)^n) / ((1 + r)^n - 1)
        numerator = r * (Decimal('1') + r) ** n
        denominator = (Decimal('1') + r) ** n - Decimal('1')
        payment = p * (numerator / denominator)
        
        return payment.quantize(Decimal('0.01'))

# Example usage
calc = FinancialCalculator()
investment = 10000
rate = 0.05
years = 10

result = calc.compound_interest(investment, rate, years)
monthly_payment = calc.loan_payment(investment, rate, years)

print(f"Investment of ${investment} at {rate*100}% for {years} years:")
print(f"Final amount: ${result}")
print(f"Monthly loan payment: ${monthly_payment}")

Real-world Application: Data Analysis with Mixed Types

This implementation demonstrates handling mixed data types in a practical data analysis scenario, incorporating boolean flags, integer counts, and float measurements.

import pandas as pd
import numpy as np
from typing import Dict, List, Union

class DataAnalyzer:
    def __init__(self, data: List[Dict[str, Union[bool, int, float]]]):
        self.df = pd.DataFrame(data)
        
    def analyze_numeric_columns(self) -> Dict[str, Dict[str, float]]:
        numeric_cols = self.df.select_dtypes(include=[np.number]).columns
        stats = {}
        
        for col in numeric_cols:
            stats[col] = {
                'mean': float(self.df[col].mean()),
                'std': float(self.df[col].std()),
                'median': float(self.df[col].median()),
                'skew': float(self.df[col].skew())
            }
        return stats
    
    def boolean_analysis(self) -> Dict[str, float]:
        bool_cols = self.df.select_dtypes(include=[bool]).columns
        results = {}
        
        for col in bool_cols:
            true_ratio = float(self.df[col].mean())
            results[col] = true_ratio
        return results

# Example usage
data = [
    {'id': i,
     'value': np.random.normal(100, 15),
     'is_valid': np.random.random() > 0.1,
     'count': np.random.randint(1, 100)}
    for i in range(1000)
]

analyzer = DataAnalyzer(data)
numeric_stats = analyzer.analyze_numeric_columns()
boolean_stats = analyzer.boolean_analysis()

print("Numeric Analysis Results:")
for col, stats in numeric_stats.items():
    print(f"\n{col}:")
    for metric, value in stats.items():
        print(f"{metric}: {value:.2f}")

print("\nBoolean Analysis Results:")
for col, ratio in boolean_stats.items():
    print(f"{col} true ratio: {ratio:.2%}")

Mathematical Operations with Mixed Types

Understanding type coercion and mathematical operations across different numeric types is crucial for scientific computing and data analysis applications.

class NumericOperations:
    @staticmethod
    def mixed_type_operations():
        # Integer and Float Operations
        int_val = 42
        float_val = 3.14159
        
        print(f"Mixed Addition: {int_val + float_val}")
        print(f"Result Type: {type(int_val + float_val)}")
        
        # Boolean Arithmetic
        bool_val = True
        print(f"Bool + Int: {bool_val + int_val}")
        print(f"Bool * Float: {bool_val * float_val}")
        
        # Complex Numbers
        complex_val = complex(1, 2)
        print(f"Complex + Float: {complex_val + float_val}")
        print(f"Complex * Int: {complex_val * int_val}")
        
        # Mathematical Functions with Mixed Types
        import math
        
        print(f"Power (int, float): {pow(int_val, float_val)}")
        print(f"Square root of float: {math.sqrt(float_val)}")
        print(f"Exponential of int: {math.exp(int_val)}")
        
        # Array Operations
        import numpy as np
        arr = np.array([int_val, float_val, bool_val])
        print(f"Array type: {arr.dtype}")
        print(f"Array operations: {arr * 2}")

# Example Usage
ops = NumericOperations()
ops.mixed_type_operations()

Type Conversion Edge Cases

Understanding edge cases in type conversion is critical for robust programming. This implementation explores boundary conditions and potential pitfalls when converting between different numeric types.

class TypeConversionHandler:
    @staticmethod
    def demonstrate_edge_cases():
        # Floating point to integer truncation
        large_float = 1e20
        try:
            int_conversion = int(large_float)
            print(f"Large float to int: {int_conversion}")
        except OverflowError as e:
            print(f"Overflow error: {e}")

        # Boolean edge cases
        print(f"bool('False'): {bool('False')}") # True (non-empty string)
        print(f"bool(''): {bool('')}")           # False (empty string)
        print(f"bool(0.0): {bool(0.0)}")        # False
        print(f"bool(0.1): {bool(0.1)}")        # True

        # Float precision limits
        small_float = 1e-308
        too_small_float = small_float / 1e308
        print(f"Very small float: {too_small_float}")  # Underflow to 0.0

        # Integer division edge cases
        print(f"-7 // 3: {-7 // 3}")  # Floor division with negative numbers
        print(f"-7 % 3: {-7 % 3}")    # Modulo with negative numbers

        # Special float values
        inf = float('inf')
        nan = float('nan')
        print(f"inf + 1: {inf + 1}")
        print(f"inf - inf: {inf - inf}")
        print(f"nan == nan: {nan == nan}")  # Always False

# Example usage
handler = TypeConversionHandler()
handler.demonstrate_edge_cases()

Advanced Real-world Application: Signal Processing

This implementation shows how different numeric types work together in a practical signal processing application, demonstrating type interactions in scientific computing.

import numpy as np
from scipy import signal
from typing import Tuple, List

class SignalProcessor:
    def __init__(self, sampling_rate: float):
        self.fs = sampling_rate
        
    def generate_signal(self, duration: float) -> Tuple[np.ndarray, np.ndarray]:
        """Generate a test signal with multiple frequency components"""
        t = np.linspace(0, duration, int(self.fs * duration), endpoint=False)
        # Generate signal with multiple frequencies
        signal_clean = (
            0.5 * np.sin(2 * np.pi * 10 * t) +  # 10 Hz component
            0.3 * np.sin(2 * np.pi * 20 * t) +  # 20 Hz component
            0.2 * np.sin(2 * np.pi * 40 * t)    # 40 Hz component
        )
        return t, signal_clean
    
    def add_noise(self, signal: np.ndarray, snr_db: float) -> np.ndarray:
        """Add Gaussian noise to signal with specified SNR"""
        signal_power = np.mean(signal ** 2)
        noise_power = signal_power / (10 ** (snr_db / 10))
        noise = np.random.normal(0, np.sqrt(noise_power), signal.shape)
        return signal + noise
    
    def apply_filter(self, noisy_signal: np.ndarray) -> np.ndarray:
        """Apply a bandpass filter"""
        nyquist = self.fs / 2
        low_cutoff = 5 / nyquist
        high_cutoff = 45 / nyquist
        b, a = signal.butter(4, [low_cutoff, high_cutoff], btype='band')
        return signal.filtfilt(b, a, noisy_signal)

# Example usage
processor = SignalProcessor(sampling_rate=1000.0)
t, clean_signal = processor.generate_signal(duration=1.0)
noisy_signal = processor.add_noise(clean_signal, snr_db=10)
filtered_signal = processor.apply_filter(noisy_signal)

# Print signal statistics
print(f"Clean signal stats:")
print(f"Mean: {np.mean(clean_signal):.6f}")
print(f"Std: {np.std(clean_signal):.6f}")
print(f"Max: {np.max(clean_signal):.6f}")

print(f"\nNoisy signal stats:")
print(f"Mean: {np.mean(noisy_signal):.6f}")
print(f"Std: {np.std(noisy_signal):.6f}")
print(f"Max: {np.max(noisy_signal):.6f}")

print(f"\nFiltered signal stats:")
print(f"Mean: {np.mean(filtered_signal):.6f}")
print(f"Std: {np.std(filtered_signal):.6f}")
print(f"Max: {np.max(filtered_signal):.6f}")

Additional Resources

  • "Python's Data Types: Internals and Implementation" - https://arxiv.org/abs/2208.14760
  • "Numerical Computing with Python: A Comprehensive Review" - https://arxiv.org/abs/2201.05935
  • "Type Systems in Scientific Computing" - https://arxiv.org/abs/2105.09077
  • Recommended search terms for further study:
    • "Python numeric type system implementation"
    • "Scientific computing with Python data types"
    • "Floating-point arithmetic in numerical analysis"
    • "Boolean algebra implementation in programming languages"

More in Data science

  1. Handling Missing Data Strategies for MCAR MAR and MNAR18 min

    Missing data mechanisms fundamentally shape our imputation strategy choices. We'll explore how to detect MCAR, MAR, and MNAR patterns using statistical tests...

  2. Exploratory Data Analysis with Python8 min

    Exploratory Data Analysis is a crucial step in the data science process, allowing us to understand the structure, patterns, and characteristics of our...

  3. Identifying and Mitigating Outlier Impacts in Data Analysis12 min

    Statistical measures like z-scores and interquartile ranges provide robust methods for detecting outliers in datasets. These approaches quantify how far data...

  4. Exploratory Data Analysis (EDA) Cheat Sheet9 min

    Understanding your dataset begins with proper loading and initial inspection. This involves reading data from various formats, checking basic properties like...

  5. Identifying and Removing Duplicates in Pandas5 min

    Duplicates in Pandas DataFrames can significantly impact data analysis by skewing results and leading to incorrect conclusions. This presentation will...

  6. Essential Python Modules for Data Science11 min

    BeautifulSoup is a powerful library for parsing HTML and XML documents, making it ideal for web scraping tasks. It provides intuitive methods to navigate...