Bird
Raised Fist0
NumPydata~20 mins

Why custom ufuncs matter in NumPy - Challenge Your Understanding

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Custom Ufunc Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of a simple custom ufunc
What is the output of this code that defines and applies a custom ufunc to a numpy array?
NumPy
import numpy as np
from numpy import vectorize

def square_plus_one(x):
    return x**2 + 1

custom_func = vectorize(square_plus_one)
arr = np.array([1, 2, 3])
result = custom_func(arr)
print(result)
A[1 2 3]
B[1 4 9]
C[2 5 10 17]
D[2 5 10]
Attempts:
2 left
💡 Hint
Remember the function squares each element and adds one.
🧠 Conceptual
intermediate
1:30remaining
Why use custom ufuncs instead of loops?
Why are custom ufuncs preferred over Python loops when applying operations on numpy arrays?
ALoops are always faster because they are simpler to understand.
BCustom ufuncs use more memory but are easier to write than loops.
CCustom ufuncs run faster because they operate element-wise in compiled code, avoiding slow Python loops.
DCustom ufuncs can only be used with integers, unlike loops.
Attempts:
2 left
💡 Hint
Think about how numpy optimizes operations internally.
❓ data_output
advanced
2:00remaining
Result of applying a custom ufunc with multiple inputs
What is the output of this code that applies a custom ufunc taking two inputs?
NumPy
import numpy as np
from numpy import vectorize

def multiply_and_add(x, y):
    return x * y + y

custom_func = vectorize(multiply_and_add)
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = custom_func(arr1, arr2)
print(result)
A[8 15 24]
B[5 10 15]
C[4 5 6]
D[4 10 18]
Attempts:
2 left
💡 Hint
Calculate x*y + y for each pair of elements.
🔧 Debug
advanced
2:00remaining
Identify the error in this custom ufunc code
What error does this code raise when defining a custom ufunc incorrectly?
NumPy
import numpy as np
from numpy import vectorize

def faulty_func(x):
    if x > 0:
        return x
    # Missing return for else case

custom_func = vectorize(faulty_func)
arr = np.array([-1, 0, 1])
result = custom_func(arr)
print(result)
ATypeError: 'NoneType' object cannot be converted to float
BValueError: operands could not be broadcast together
CTypeError: unsupported operand type(s) for >: 'numpy.ndarray' and 'int'
DTypeError: 'NoneType' object cannot be interpreted as an integer
Attempts:
2 left
💡 Hint
Think about what happens if the function returns nothing for some inputs.
🚀 Application
expert
2:30remaining
Why create custom ufuncs for complex operations?
Which reason best explains why creating custom ufuncs is important for complex data science tasks?
AThey automatically parallelize code across multiple CPUs without any extra work.
BThey allow vectorized operations on arrays with custom logic, improving speed and code clarity.
CThey replace the need for any other numpy functions in data science workflows.
DThey reduce the size of data arrays by compressing values during computation.
Attempts:
2 left
💡 Hint
Think about the benefits of vectorization and custom logic combined.

Practice

(1/5)
1. Why do custom ufuncs matter in numpy?
easy
A. They let you apply your own functions element-wise on arrays easily.
B. They are used to create plots from arrays.
C. They replace the need for Python loops in all cases.
D. They automatically fix errors in array data.

Solution

  1. Step 1: Understand the purpose of custom ufuncs

    Custom ufuncs allow you to apply your own math or logic functions element-wise on numpy arrays, making operations simpler.
  2. Step 2: Compare with other options

    The other options describe unrelated or incorrect uses of custom ufuncs.
  3. Final Answer:

    They let you apply your own functions element-wise on arrays easily. -> Option A
  4. Quick Check:

    Custom ufuncs = element-wise custom functions [OK]
Hint: Custom ufuncs = your function applied to each array item [OK]
Common Mistakes:
  • Thinking custom ufuncs create plots
  • Believing they fix data errors automatically
  • Confusing them with general Python loops
2. Which of the following is the correct way to create a custom ufunc using np.vectorize?
easy
A. ufunc = np.vectorize(my_function())
B. ufunc = np.vectorize[my_function]
C. ufunc = np.vectorize(my_function)
D. ufunc = np.vectorize{my_function}

Solution

  1. Step 1: Recall the syntax of np.vectorize

    The correct syntax to create a vectorized function is np.vectorize(function_name) without brackets after the function name.
  2. Step 2: Analyze each option

    ufunc = np.vectorize(my_function) uses parentheses correctly. ufunc = np.vectorize[my_function] uses square brackets which is invalid. ufunc = np.vectorize{my_function} uses curly braces which is invalid. ufunc = np.vectorize(my_function()) calls the function immediately, which is incorrect.
  3. Final Answer:

    ufunc = np.vectorize(my_function) -> Option C
  4. Quick Check:

    np.vectorize(function) uses parentheses [OK]
Hint: Use parentheses with np.vectorize, not brackets or braces [OK]
Common Mistakes:
  • Using square brackets instead of parentheses
  • Calling the function inside np.vectorize
  • Using curly braces instead of parentheses
3. What is the output of this code?
import numpy as np

def square_plus_one(x):
    return x**2 + 1

vec_func = np.vectorize(square_plus_one)
arr = np.array([1, 2, 3])
print(vec_func(arr))
medium
A. [2 5 10]
B. [1 4 9]
C. [1 2 3]
D. [3 5 7]

Solution

  1. Step 1: Understand the function applied

    The function squares the input and adds 1: x**2 + 1.
  2. Step 2: Apply function to each array element

    For arr = [1, 2, 3]: 1**2+1=2, 2**2+1=5, 3**2+1=10.
  3. Final Answer:

    [2 5 10] -> Option A
  4. Quick Check:

    Square plus one applied element-wise = [2 5 10] [OK]
Hint: Apply function to each element: square then add one [OK]
Common Mistakes:
  • Forgetting to add 1 after squaring
  • Confusing output with original array
  • Mixing up element-wise operation
4. Identify the error in this code that tries to create a custom ufunc:
import numpy as np

def add_three(x):
    return x + 3

ufunc = np.vectorize(add_three())
arr = np.array([1, 2, 3])
print(ufunc(arr))
medium
A. Missing import statement for numpy.
B. Calling add_three() inside np.vectorize instead of passing the function.
C. Using np.vectorize instead of np.frompyfunc.
D. Array arr is not defined.

Solution

  1. Step 1: Check how np.vectorize is called

    np.vectorize expects a function, but add_three() calls the function immediately, passing its result instead.
  2. Step 2: Understand the impact of the error

    Calling add_three() returns an integer, not a function, causing np.vectorize to fail or behave incorrectly.
  3. Final Answer:

    Calling add_three() inside np.vectorize instead of passing the function. -> Option B
  4. Quick Check:

    Pass function name, don't call it inside np.vectorize [OK]
Hint: Pass function name to np.vectorize, don't call it [OK]
Common Mistakes:
  • Calling function inside np.vectorize
  • Confusing function call with function reference
  • Ignoring error messages about wrong argument type
5. You want to create a custom ufunc that returns the sign of each element in an array: -1 if negative, 0 if zero, and 1 if positive. Which code correctly creates and applies this ufunc to np.array([-2, 0, 3])?
hard
A. def sign_func(x): if x <= 0: return 1 else: return -1 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3])))
B. def sign_func(x): return x > 0 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3])))
C. def sign_func(x): return x sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3])))
D. def sign_func(x): if x < 0: return -1 elif x == 0: return 0 else: return 1 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3])))

Solution

  1. Step 1: Understand the sign function requirements

    The function must return -1 for negative, 0 for zero, and 1 for positive values.
  2. Step 2: Check each option's logic

    def sign_func(x): if x < 0: return -1 elif x == 0: return 0 else: return 1 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3]))) correctly implements the conditions. def sign_func(x): return x > 0 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3]))) returns True/False, not -1/0/1. def sign_func(x): return x sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3]))) returns the value itself, not the sign. def sign_func(x): if x <= 0: return 1 else: return -1 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3]))) reverses sign logic and misses zero case.
  3. Final Answer:

    def sign_func(x): if x < 0: return -1 elif x == 0: return 0 else: return 1 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3]))) -> Option D
  4. Quick Check:

    Correct sign logic with if-elif-else = def sign_func(x): if x < 0: return -1 elif x == 0: return 0 else: return 1 sign_ufunc = np.vectorize(sign_func) print(sign_ufunc(np.array([-2, 0, 3]))) [OK]
Hint: Use if-elif-else to cover negative, zero, positive cases [OK]
Common Mistakes:
  • Returning boolean instead of -1,0,1
  • Ignoring zero case
  • Reversing sign conditions
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard