Skip to content

Vectorize lorenz_curve and gini#702

Open
Smit-create wants to merge 1 commit into
QuantEcon:mainfrom
Smit-create:opt
Open

Vectorize lorenz_curve and gini#702
Smit-create wants to merge 1 commit into
QuantEcon:mainfrom
Smit-create:opt

Conversation

@Smit-create

@Smit-create Smit-create commented Apr 19, 2023

Copy link
Copy Markdown
Member
  • Replaced the python loops with vectorized code for enhancing the performance in lorenz_curve and gini_coefficient.

@coveralls

coveralls commented Apr 19, 2023

Copy link
Copy Markdown

Coverage Status

Coverage: 92.988% (+0.01%) from 92.975% when pulling c448868 on Smit-create:opt into eeb0865 on QuantEcon:main.

@Smit-create Smit-create requested review from jstac, mmcky and oyamad April 20, 2023 06:23

@oyamad oyamad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add tests?

@Smit-create

Copy link
Copy Markdown
Member Author

Hmm, The tests are already present in https://github.com/QuantEcon/QuantEcon.py/blob/main/quantecon/tests/test_inequality.py so I thought to skip adding them.

@oyamad

oyamad commented Apr 23, 2023

Copy link
Copy Markdown
Member

Is this adding new features or refactoring the code?

@Smit-create

Copy link
Copy Markdown
Member Author

This is just refactoring the code and removing some for loops for performance optimizations.

@oyamad

oyamad commented Apr 24, 2023

Copy link
Copy Markdown
Member

@Smit-create It is usually advised to use for loops (and avoid creation of intermediate arrays) in njited functions. Do you have a reason to go against that in this case?

@Smit-create

Copy link
Copy Markdown
Member Author

It is usually advised to use for loops (and avoid creation of intermediate arrays) in njited functions.

I found this better in terms of time performance as this is vectorized version while the extra space complexity (creating new arrays) is still the same for both the functions -- O(n)

@mmcky

mmcky commented Apr 27, 2023

Copy link
Copy Markdown
Contributor

@Smit-create thanks for opening this PR.

Would you mind to update the top level comment box with a description of the change and document the performance improvements you mention in this thread so it's clear what this change is about.

@Smit-create

Copy link
Copy Markdown
Member Author

Thanks @mmcky. Done

@mmcky

mmcky commented Oct 24, 2023

Copy link
Copy Markdown
Contributor

@Smit-create I haven't merged this as it isn't clear what level of performance improvement is being made. Is it 2% or 20% for example, it would be helpful to have timings between the different versions to make an assessment here. @oyamad makes a good point around njit so we need a clear reason to change to vectorized code.

@mmcky mmcky requested a review from Copilot August 16, 2025 01:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR vectorizes the lorenz_curve and gini_coefficient functions to improve performance by replacing Python loops with NumPy vectorized operations. The changes eliminate explicit iteration in favor of array operations that can be optimized by NumPy's underlying C implementations.

Key changes:

  • Replace manual loop-based cumulative calculations in lorenz_curve with vectorized NumPy operations
  • Optimize gini_coefficient by reducing nested loops and using vectorized absolute difference calculations
  • Remove trailing whitespace

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Comment thread quantecon/_inequality.py
"""

n = len(y)
n = y.shape[0]

Copilot AI Aug 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using y.shape[0] instead of len(y) is inconsistent with the pattern used elsewhere in the function (line 76 still uses len(y)). Consider keeping len(y) for consistency, as it works for both arrays and lists.

Suggested change
n = y.shape[0]
n = len(y)

Copilot uses AI. Check for mistakes.
Comment thread quantecon/_inequality.py
i_sum[i] += abs(y[i] - y[j])
return np.sum(i_sum) / (2 * n * np.sum(y))
i_sum += np.sum(np.abs(y[i] - y))
t_sum += y[i]

Copilot AI Aug 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This vectorization still contains a loop over i and computes np.abs(y[i] - y) for each element, which may not provide the expected performance improvement. Consider fully vectorizing using broadcasting: np.sum(np.abs(y[:, np.newaxis] - y[np.newaxis, :])) to eliminate the loop entirely.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants