Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional 7-day smoothing window #25

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pypistats/templates/package.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ <h1>{{ package }}</h1>
<br>
Downloads last month:
{{ "{:,.0f}".format(recent['month']) }}
<br>
<input type="checkbox" id="smoothing" {{ 'checked' if metadata['use_smoothing'] else ''}} onclick="return setSmoothing();"> 7-day smoothing
</p>
<script>

Expand Down Expand Up @@ -93,5 +95,14 @@ <h1>{{ package }}</h1>
}
};
})();

function setSmoothing() {
if (document.getElementById('smoothing').checked) {
window.location='{{ url_for('general.package_page', package=package) }}?smooth=true';
} else {
window.location='{{ url_for('general.package_page', package=package) }}';
}
return false;
}
</script>
{% endblock %}
39 changes: 35 additions & 4 deletions pypistats/views/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def package_page(package):
recent[r.category] = r.downloads

# PyPI metadata
metadata = None
metadata = dict()
if package != "__all__":
try:
metadata = requests.get(f"https://pypi.python.org/pypi/{package}/json", timeout=5).json()
Expand All @@ -134,8 +134,13 @@ def package_page(package):
else:
metrics = ["downloads", "percentages"]

use_smoothing = metadata['use_smoothing'] = request.args.get('smooth', None) is not None
for metric in metrics:
model_data.append({"metric": metric, "name": model.__tablename__, "data": data_function[metric](records)})
model_data.append({
"metric": metric,
"name": model.__tablename__,
"data": data_function[metric](records, use_smoothing=use_smoothing),
})

# Build the plots
plots = []
Expand Down Expand Up @@ -186,7 +191,22 @@ def package_page(package):
return render_template("package.html", package=package, plots=plots, metadata=metadata, recent=recent, user=g.user)


def get_download_data(records):
def smooth_data(data, window=7):
# Ensure data is sorted by date
data["x"], data["y"] = zip(*[(x, y) for x, y in sorted(
zip(data["x"], data["y"]), key=lambda pair: pair[0])])
# Smooth data on a rolling window
smoothed_data = deepcopy(data)
smoothed_data["y"] = list(smoothed_data["y"])
for i in range(len(data["y"])):
window_start = max(0, i - window // 2)
window_end = min(len(data["y"]), i + window // 2 + 1)
window_data = data["y"][window_start:window_end]
smoothed_data["y"][i] = sum(window_data) / len(window_data)
return smoothed_data


def get_download_data(records, use_smoothing=False):
"""Organize the data for the absolute plots."""
data = defaultdict(lambda: {"x": [], "y": []})

Expand Down Expand Up @@ -236,10 +256,16 @@ def get_download_data(records):
if category not in date_categories:
data[category]["x"].append(str(records[-1].date))
data[category]["y"].append(0)

if use_smoothing:
# Smooth data using a 7-day window
for category in all_categories:
data[category] = smooth_data(data[category])

return data


def get_proportion_data(records):
def get_proportion_data(records, use_smoothing=False):
"""Organize the data for the fill plots."""
data = defaultdict(lambda: {"x": [], "y": [], "text": []})

Expand Down Expand Up @@ -285,6 +311,11 @@ def get_proportion_data(records):
data[category]["y"].append(value)
data[category]["text"].append("{0:.2f}%".format(value) + " = {:,}".format(date_categories[category]))

if use_smoothing:
# Smooth data using a 7-day window
for category in all_categories:
data[category] = smooth_data(data[category])

return data


Expand Down