Chapter 4: Introduction to Python for R Users

Introduction

This tutorial introduces Python programming with a focus on comparisons to R. If you’re familiar with R, you’ll find many concepts translate directly, though the syntax differs. Python is a general-purpose programming language that’s become increasingly popular in data science, offering powerful libraries for data manipulation, visualization, and machine learning.

Setting Up

Python can be run in various environments:

  • RStudio/Positron (see this blog post: Using Python in RStudio)
  • Jupyter notebooks (similar to RMarkdown/Quarto)
  • VSCode with Python extensions

For this tutorial, we’ll use Python code chunks in Quarto, which can execute Python code just like they execute R code.

# This is a comment in Python (like # in R)
print("Hello from Python!")
Hello from Python!

Python Environments

What Are Environments?

One of the biggest differences between Python and R is how they handle packages and dependencies. In R, when you install a package with install.packages(), it typically goes into a central library that all your R projects share. Python takes a different approach with virtual environments.

A Python environment is an isolated directory that contains:

  • A specific Python version
  • Installed packages and their specific versions
  • Dependencies for those packages

Imagine you have Project A that needs version 1.0 of a package, and Project B needs version 2.0 of the same package. In R, you’d typically have one version installed. In Python, you create separate environments for each project.

Common Environment Tools

We will use conda for all things environment management in this tutorial. Other options include: - venv (built-in Python tool) - virtualenv (third-party tool)

conda is more powerful and manages both Python versions and packages. It’s popular in data science.

# Create environment with specific Python version
conda create -n toolbox_env python=3.9

# Activate
conda activate toolbox_env

# Install packages
conda install pandas numpy matplotlib selenium openpyxl

# Deactivate
conda deactivate

Or do it the reticulate way in Quarto:

reticulate::conda_create("toolbox_env", packages = "python=3.9")
reticulate::conda_install("toolbox_env", packages = c("pandas", "numpy", "matplotlib", "selenium", "openpyxl"))
reticulate::use_condaenv("toolbox_env", required = TRUE)

Why Environments Matter for This Tutorial

If you’re working through this tutorial:

  1. Using Jupyter/Quarto: These typically run in their own environment. Your code chunks will execute in whatever environment is active.

  2. Installing packages: When we eventually use packages like NumPy, selenium, or Pandas, you’ll want to install them in an environment:

conda install pandas numpy matplotlib selenium
  1. Checking your environment: You can see what’s installed with:
conda list            # for conda

Quick Setup Recommendation

If you have not created your environment using reticulate yet, I recommend doing it manually in the console.

# Create a dedicated environment
conda create -n toolbox_env python=3.9 pandas numpy matplotlib jupyter

# Activate it
conda activate toolbox_env

# When working on exercises, make sure this environment is active!
Compared to R

Think of it this way: In R, you might use RStudio Projects to organize your work. In Python, you use Projects plus environments to isolate not just files, but also package versions.

Checking Your Current Environment

import sys

# Where is Python running from?
print(f"Python executable: {sys.executable}")

# What version?
print(f"Python version: {sys.version}")

If you’re using conda, you can also check in your terminal:

conda info --envs  # List all environments

Data Types

Python has several fundamental data types. Unlike R, where everything is a vector by default, Python distinguishes between individual values (scalars) and collections. You will also use an assignment operator = instead of <-.

Numbers

Python has two main numeric types: integers (int) and floating-point numbers (float).

# Integer
x = 42
print(type(x))  # Check the type
<class 'int'>
print(x)
42
# Float
y = 3.14159
print(type(y))
<class 'float'>
print(y)
3.14159
Compared to R

In R, you’d use class() instead of type(). R doesn’t strictly distinguish between integers and doubles unless you explicitly create an integer with 42L.

Strings

Strings represent text data. Python treats single quotes ' and double quotes " identically (unlike R where they’re essentially the same but double quotes are conventional).

# Strings in Python
greeting = "Hello"
name = 'World'

# String concatenation uses +
message = greeting + " " + name + "!"
print(message)
Hello World!
# Or use f-strings (formatted string literals) -- Python 3.6+
message_formatted = f"{greeting} {name}!"
print(message_formatted)
Hello World!
Compared to R

In R, you’d use paste() or paste0() for concatenation, or str_c() from the tidyverse. Python’s f-strings are similar to glue::glue() in R.

Booleans

Boolean values are True and False (note the capitalization - this matters in Python!).

# Booleans in Python
is_python_fun = True
is_this_hard = False

print(is_python_fun)
True
print(type(is_python_fun))
<class 'bool'>
Compared to R

R uses TRUE and FALSE (all caps), while Python uses True and False (capitalized). Python is case-sensitive, so true would throw an error.

None

Python’s equivalent of R’s NULL or NA is None.

# None represents absence of value
nothing = None
print(nothing)
None
print(type(nothing))
<class 'NoneType'>

Collections: Lists, Tuples, and Dictionaries

Python has several built-in collection types. These are roughly analogous to R’s vectors and lists, but with important differences.

Lists

Python lists are ordered, mutable (changeable) collections. They’re similar to R’s lists, not R’s atomic vectors.

# Creating a list
numbers = [1, 2, 3, 4, 5]
mixed_list = [1, "two", 3.0, True]  # Can contain different types

print(numbers)
[1, 2, 3, 4, 5]
print(mixed_list)
[1, 'two', 3.0, True]

Indexing: Python uses 0-based indexing (the first element is at position 0), unlike R’s 1-based indexing.

# Accessing elements
fruits = ["apple", "banana", "cherry", "date"]

print(fruits[0])      # First element (R would use fruits[1])
apple
print(fruits[-2])     # Last element (negative indexing from end)
cherry
print(fruits[1:3])    # Slicing: elements 1 and 2 (end index is exclusive)
['banana', 'cherry']
Compared to R

R’s c(1, 2, 3, 4, 5) creates an atomic vector. Python’s [1, 2, 3, 4, 5] is more like R’s list(1, 2, 3, 4, 5), though it can be used for numeric operations when converted to a NumPy array.

Some common list operations:

# List operations
numbers = [1, 2, 3]

# Append (like R's c() or append())
numbers.append(4)
print(numbers)
[1, 2, 3, 4]
# Extend with another list
numbers.extend([5, 6])
print(numbers)
[1, 2, 3, 4, 5, 6]
# Length
print(len(numbers))  # R's length()
6

Tuples

Tuples are like lists but immutable (can’t be changed after creation). They use parentheses () instead of square brackets.

# Creating a tuple
coordinates = (10, 20)
print(coordinates)
(10, 20)
print(type(coordinates))
<class 'tuple'>
# Accessing works the same as lists
print(coordinates[0])
10

# But you can't modify them
#coordinates[0] = 15  # This would raise an error!
Compared to R

R doesn’t have a direct equivalent to tuples, though you could think of them as named lists that are “frozen.”

Dictionaries

Dictionaries store key-value pairs. They’re similar to R’s named lists or named vectors.

# Creating a dictionary
person = {
    "name": "Alice",
    "age": 30,
    "city": "Leipzig"
}

print(person)
{'name': 'Alice', 'age': 30, 'city': 'Leipzig'}
# Accessing values by key
print(person["name"])
Alice
print(person["age"])
30
# Adding new key-value pairs
person["occupation"] = "Data Scientist"
print(person)
{'name': 'Alice', 'age': 30, 'city': 'Leipzig', 'occupation': 'Data Scientist'}
Compared to R

This is similar to:

person <- list(
  name = "Alice",
  age = 30,
  city = "Leipzig"
)
person$name  # or person[["name"]]

Simple Operations

Arithmetic Operations

Python supports standard arithmetic operators, similar to R.

# Basic arithmetic
a = 11
b = 3

a + b       # Addition
14
a - b       # Subtraction
8
a * b       # Multiplication
33
a / b       # Division (always returns float)
3.6666666666666665
a // b      # Floor division (integer division - R uses %/%)
3
a % b       # Modulus (remainder)
2
a ** b      # Exponentiation (R uses a^b or a**b in newer versions)
1331
Compared to R

Most operators are the same.

Key differences:

  • / always returns float in Python 3 (R returns integer if both are integers)
  • // for integer division (R: %/%)
  • ** for exponentiation (R traditionally uses ^, though ** now works)

Comparison Operations

# Comparison operators
x = 5
y = 10

x == y #Equal
False
x != y # Not equal
True
x > y  # Greater than
False
x <= y # Less than or equal to
True
Compared to R

Same operators, but Python uses != for “not equal” (R can use != or <>).

Logical Operations

Python uses words instead of symbols for logical operations.

# Logical operators
a = True
b = False

a and b # R equ: a & b
False
a or b # R equ: a | b
True
not a # R equ: !a
False
Compared to R
  • Python: and, or, not
  • R: &, |, ! (for element-wise); &&, || (for scalar)

Flow Control with if, elif, else

Sometimes you want your code to only run in specific cases. Python uses if statements for conditional execution.

# Basic if statement
x = 3

if x <= 5:
    print("x is smaller than or equal to 5")
x is smaller than or equal to 5

Add an else block for an alternative action:

x = 10

if x <= 5:
    print("x is smaller than or equal to 5")
else:
    print("x is greater than 5")
x is greater than 5

elif - Multiple Conditions

When you need to check multiple conditions sequentially, use elif (short for “else if”). Python will check each condition in order and execute the first block where the condition is True.

score = 75

if score >= 90:
    print("Grade: A")
elif score >= 80:
    print("Grade: B")
elif score >= 70:
    print("Grade: C")
elif score >= 60:
    print("Grade: D")
else:
    print("Grade: F")
Grade: C

You can have as many elif statements as you need. Python checks them from top to bottom and stops at the first True condition. Note that the final else is optional but highly recommended as a catch-all.

temperature = 25

if temperature < 0:
    print("Freezing!")
elif temperature < 10:
    print("Cold")
elif temperature < 20:
    print("Cool")
elif temperature < 30:
    print("Warm")
else:
    print("Hot!")
Warm
Compared to R

Comparison to R: R uses else if (two words) instead of elif:

temperature = 25
if (temperature < 0) {
  print("Freezing")
} else if (temperature >= 10) {
  print("Cold")
} else if (temperature < 20) {
  print("Cool")
} else if (temperature < 30) {
  print("Warm")
} else {
  print("Hot!")
}
[1] "Cold"

Important: The condition must evaluate to a single boolean value (True or False).

Functions

Functions allow you to package code into reusable blocks. Just like in R, functions are essential for writing clean, maintainable code that follows the DRY (Don’t Repeat Yourself) principle.

Defining Functions

The basic syntax for defining a function in Python:

def function_name(parameter1, parameter2):
    """This is a docstring - describes what the function does."""
    # Function body
    result = parameter1 + parameter2
    return result

# Call the function
answer = function_name(5, 3)
answer
8
Compared to R
function_name <- function(parameter1, parameter2) {
  result <- parameter1 + parameter2
  return(result)
}

A Simple Example

def greet(name):
    """Greet someone by name."""
    return f"Hello, {name}!"

greet("Alice")
'Hello, Alice!'
greet("Bob")
'Hello, Bob!'

### Hint: Python coders tend to use "" around real text/natural language and '' around symbol-like expressions (e.g., column names -- see below)

Default Arguments

You can provide default values for parameters, just like in R.

def greet_with_title(name, title = "Dr."):
    """Greet someone with their title."""
    return f"Hello, {title} {name}!"

greet_with_title("Smith")                    # Uses default title
'Hello, Dr. Smith!'
greet_with_title("Smith", "Prof.")           # Overrides default
'Hello, Prof. Smith!'
greet_with_title("Smith", title = "Mr.")       # Named argument (more explicit)
'Hello, Mr. Smith!'
Compared to R
rgreet_with_title <- function(name, title = "Dr.") {
  paste0("Hello, ", title, " ", name, "!")
}

return

Per the official style guide it is idiomatic to be consistent with return statements:

Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable)

Compared to R

The object created in the last call will automatically be returned. return(object) shall be avoided unless you need an early return.

Multiple Return Values

Python can return multiple values as a tuple (similar to R’s lists).

def calculate_stats(numbers):
    """Calculate mean and standard deviation."""
    n = len(numbers)
    mean = sum(numbers) / n
    
    # Calculate standard deviation
    squared_diff = [(x - mean) ** 2 for x in numbers] # this is a list comprehension, an abbreviated for loop
    variance = sum(squared_diff) / n
    std_dev = variance ** 0.5
    
    return mean, std_dev  # Returns a tuple

data = [2, 4, 4, 4, 5, 5, 7, 9]

mean_value, std_value = calculate_stats(data) # make sure to define both objects, or unpack the tuple later
mean_value
5.0
std_value
2.0
#this is the same as:
results = calculate_stats(data)
mean_value = results[0]
std_value = results[1]
mean_value
5.0
std_value
2.0
Compared to R

Comparison to R: R typically returns a list or vector:

rcalculate_stats <- function(numbers) {
  list(mean = mean(numbers), sd = sd(numbers))
}

Docstrings

Python uses triple-quoted strings (“““…”““) right after the function definition to document what the function does. This is similar to roxygen2 comments in R.

def convert_temperature(celsius):
    """
    Convert temperature from Celsius to Fahrenheit.
    
    Parameters:
    -----------
    celsius : float
        Temperature in Celsius
        
    Returns:
    --------
    float
        Temperature in Fahrenheit
    """
    fahrenheit = (celsius * 9/5) + 32
    return fahrenheit

convert_temperature(0)
32.0
convert_temperature(100)
212.0

#'You can access the docstring with `help()` in an interactive session (e.g., Jupyter):
#help(convert_temperature)

Lambda Functions (Anonymous Functions)

Python has lambda functions for short, one-line functions. These are similar to R’s anonymous functions function(x) x + 1 or the shorthand \(x) x + 1 in purrr.

# Regular function
def add_ten(x):
    return x + 10

# Lambda function (anonymous)
add_ten_lambda = lambda x: x + 10

add_ten(5)
15
add_ten_lambda(5)
15

Lambda functions are especially useful when you need a simple function as an argument:

# Sort a list of tuples by the second element
pairs = [(1, 'one'), (3, 'three'), (2, 'two')]
sorted_pairs = sorted(pairs, key=lambda x: x[1])
sorted_pairs
[(1, 'one'), (3, 'three'), (2, 'two')]
Compared to R

R equivalent

add_ten <- function(x) x + 10
# or in purrr
add_ten <- \(x) x + 10

Variable Scope

Python follows similar scoping rules to R: variables defined inside functions are local to that function.

x = 10  # Global variable

def modify_variable():
    x = 5  # Local variable - doesn't affect global x
    return x

modify_variable()  # Returns 5
5
x                  # Still 10
10

To modify a global variable inside a function, you need the global keyword (though this is generally discouraged):

counter = 0

def increment_counter():
    global counter
    counter += 1
    return counter

increment_counter()
1
increment_counter()
2
counter
2
Compared to R

Comparison to R: R uses <<- for assigning to parent environments, which is also discouraged.

Loops

Loops allow you to repeat operations. Python has for loops and while loops, similar to R.

For Loops

for loops in Python iterate over sequences (lists, tuples, strings, ranges, etc.).

# Basic for loop
fruits = ["apple", "banana", "cherry"]

for fruit in fruits:
    print(f"I like {fruit}")
I like apple
I like banana
I like cherry
Compared to R

R’s equivalent would be:

fruits = c("apple", "banana", "cherry")
for (fruit in fruits) {
  print(paste("I like", fruit))
}
[1] "I like apple"
[1] "I like banana"
[1] "I like cherry"

The range() Function

range() generates a sequence of numbers and is commonly used with for loops. It’s similar to R’s seq() or : operator.

# range(stop) - from 0 to stop-1
for i in range(5):
    print(i)
0
1
2
3
4
# range(start, stop) - from start to stop-1
for i in range(2, 7):
    print(i)
2
3
4
5
6
# range(start, stop, step) - with custom step
for i in range(0, 10, 2):
    print(i)
0
2
4
6
8
Compared to R

R equivalents:

for (i in 0:4) { }           # range(5)
for (i in 2:6) { }           # range(2, 7)
for (i in seq(0, 8, by=2)) { } # range(0, 10, 2)

Enumerate

When you need both the index and the value, use enumerate().

# enumerate provides index and value
colors = ["red", "green", "blue"]
enumerate(colors)
<enumerate object at 0x122b01480>
for index, color in enumerate(colors):
    print(f"Color {index}: {color}")
Color 0: red
Color 1: green
Color 2: blue
# Start counting from 1 instead of 0
for index, color in enumerate(colors, start=1):
    print(f"Color {index}: {color}")
Color 1: red
Color 2: green
Color 3: blue
Compared to R

R’s seq_along() is similar:

colors = c("red", "green", "blue")
for (i in seq_along(colors)) {
  print(paste("Color", i, ":", colors[i]))
}
[1] "Color 1 : red"
[1] "Color 2 : green"
[1] "Color 3 : blue"

Nested Loops

You can nest loops just like in R.

# Nested loops - multiplication table
for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i} x {j} = {i * j}")
1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9

List Comprehensions

One of Python’s most powerful features is list comprehensions – a concise way to create lists. This is similar to R’s sapply() or purrr::map().

Now that you understand for loops, list comprehensions will make more sense as they’re essentially condensed for loops. List comprehensions will yield a list.

# Traditional loop approach
squares = [] # define list
for i in range(1, 6):
    squares.append(i ** 2) # build list as you go -- more efficient than vector growing in R
print(squares)
[1, 4, 9, 16, 25]
# List comprehension - more Pythonic
squares = [i ** 2 for i in range(1, 6)]
print(squares)
[1, 4, 9, 16, 25]
# With condition (like dplyr::filter)
#[expression *for* item *in* iterable *if* condition]
even_squares = [i ** 2 for i in range(1, 11) if i % 2 == 0]
print(even_squares)
[4, 16, 36, 64, 100]
Compared to R

R equivalent:

needs(tidyverse)
squares <- sapply(1:5, function(x) x^2)
# or with purrr
squares <- map(1:5, \(x) x^2)

The general syntax for list comprehensions is:

[expression *for* item *in* iterable *if* condition]

This reads almost like English: “Create a list of expression for each item in iterable if condition is true.”

While Loops

while loops continue executing as long as a condition is True. They’re identical in concept to R’s while loops.

# Basic while loop
count = 0

while count < 5:
    print(f"Count is: {count}")
    count += 1  # Increment 
Count is: 0
Count is: 1
Count is: 2
Count is: 3
Count is: 4
print("Loop finished!")
Loop finished!
Compared to R

Very similar syntax, though Python uses count += 1 instead of count <- count + 1.

# while loop with user input simulation
# Let's simulate checking until we find a value
import random

target = 7
attempts = 0
guess = 0

while guess != target:
    guess = random.randint(1, 10)
    attempts += 1
    print(f"Attempt {attempts}: guessed {guess}")
Attempt 1: guessed 10
Attempt 2: guessed 8
Attempt 3: guessed 3
Attempt 4: guessed 3
Attempt 5: guessed 3
Attempt 6: guessed 5
Attempt 7: guessed 3
Attempt 8: guessed 6
Attempt 9: guessed 1
Attempt 10: guessed 1
Attempt 11: guessed 10
Attempt 12: guessed 5
Attempt 13: guessed 8
Attempt 14: guessed 9
Attempt 15: guessed 5
Attempt 16: guessed 9
Attempt 17: guessed 7
print(f"Found {target} in {attempts} attempts!")
Found 7 in 17 attempts!

break and continue

Control loop execution with break and continue.

# break - exit the loop immediately
for i in range(10):
    if i == 5:
        break
    print(i)
0
1
2
3
4
# continue - skip rest of current iteration
for i in range(10):
    if i % 2 == 0:  # Skip even numbers
        continue
    print(i)
1
3
5
7
9
Compared to R

break and next work the same way (next in R is continue in Python).

Practical Examples

Example 1: Filter and Transform Data Let’s say we have a list of student grades and we want to filter out those who passed (grade >= 70) and calculate the average grade.

# Sample data
students = [
    {"name": "Alice", "grade": 85},
    {"name": "Bob", "grade": 72},
    {"name": "Charlie", "grade": 90},
    {"name": "Diana", "grade": 68},
    {"name": "Eve", "grade": 95}
]

# Filter students who passed (grade >= 70)
passing_students = [s for s in students if s["grade"] >= 70]

print("Passing students:")
Passing students:
for student in passing_students:
    print(f"{student['name']}: {student['grade']}")
Alice: 85
Bob: 72
Charlie: 90
Eve: 95
# Calculate average grade
grades = [s["grade"] for s in students]
average = sum(grades) / len(grades)
print(f"\nClass average: {average:.2f}")

Class average: 82.00
Compared to R

This is similar to using dplyr::filter() and summarize().

Example 2: FizzBuzz

A classic programming exercise - counting with special rules.

# FizzBuzz: Print numbers 1-20, but:
# - "Fizz" for multiples of 3
# - "Buzz" for multiples of 5
# - "FizzBuzz" for multiples of both

for i in range(1, 21):
    if i % 3 == 0 and i % 5 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz

Key Python Conventions

Indentation

Python uses indentation to define code blocks (unlike R which uses {}). This is not optional – incorrect indentation will cause errors!

Correct indentation

if True:
    print("This is indented")
    print("This too")
This is indented
This too
print("This is not in the if block")
This is not in the if block

Important: Use 4 spaces (not tabs) for indentation. Most Python editors handle this automatically.

Naming Conventions

Python follows PEP 8 style guide:

  • Variables and functions: snake_case (like R’s tidyverse)
  • Constants: UPPER_CASE
  • Classes: PascalCase
# Good Python style
student_name = "Alice"
MAX_ATTEMPTS = 3

def calculate_average(values):
    return sum(values) / len(values)

Finally: The Zen of Python

Python has a philosophy! Type import this to see it:

import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Exercises

Exercise 1: Temperature Converter Write a program that converts temperatures between Celsius and Fahrenheit. Formula: \(F = (C \times 9/5) + 32\)

  1. Convert each to Fahrenheit using a for loop
  2. Print the results
  3. Store each Celsius value and its Fahrenheit equivalent in a DataFrame.
Solution. Click to expand!
temperatures_celsius = [0, 10, 20, 30, 40]
temperatures_fahrenheit = []

for temp in temperatures_celsius:
    fahrenheit = (temp * 9/5) + 32
    temperatures_fahrenheit.append(fahrenheit)

temperatures_fahrenheit
[32.0, 50.0, 68.0, 86.0, 104.0]

Exercise 2: Word Counter

Given a sentence, count how many times each word appears.

Hint: Use sentence.split() to get a list of words, and a dictionary to store counts. The operator in yields True if an element is in another list, e.g., if word in word_counts

Solution. Click to expand!
python_sentence = "the quick brown fox jumps over the lazy dog the fox"

# Split sentence into words
words = python_sentence.split()

# Count occurrences using a dictionary
word_counts = {}
for word in words:
    if word in word_counts:
        word_counts[word] += 1
    else:
        word_counts[word] = 1

word_counts
{'the': 3, 'quick': 1, 'brown': 1, 'fox': 2, 'jumps': 1, 'over': 1, 'lazy': 1, 'dog': 1}
# Expected output: {'the': 3, 'quick': 1, 'brown': 1, ...}

Exercise 3: Prime Numbers

Write a function that checks if a number is prime. Then use it to find all prime numbers between 1 and 50.

Solution. Click to expand!
def is_prime(n):
    """Check if a number is prime"""
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    for i in range(3, n):
        if n % i == 0:
            return False
    return True

is_prime(50)
False
# Find all prime numbers between 1 and 50
primes = []
for num in range(1, 51):
    if is_prime(num):
        primes.append(num)

primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Exercise 4: List Manipulation

  1. Create a list of numbers from 1 to 20:
  2. Create a new list with only even numbers
  3. Create a new list with squares of odd numbers
  4. Calculate the sum of numbers divisible by 3
Solution. Click to expand!
# a. Create a list of numbers from 1 to 20
numbers = list(range(1, 21))

# b. Create a new list with only even numbers
even_numbers = [num for num in numbers if num % 2 == 0]
even_numbers
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# c. Create a new list with squares of odd numbers
odd_squares = [num ** 2 for num in numbers if num % 2 != 0]
odd_squares
[1, 9, 25, 49, 81, 121, 169, 225, 289, 361]
# d. Calculate the sum of numbers divisible by 3
divisible_by_3 = [num for num in numbers if num % 3 == 0]
sum(divisible_by_3)
63

The syntax might be different, but the concepts you know from R will translate well!

Further Resources