I have a dictionary:
{
"account": "x*", 'amount': 300, 'day': 3, 'month': 'June',
"account": "y*", 'amount': 550, 'day': 9, 'month': 'May',
"account": 'z*', 'amount': -200, 'day': 21, 'month': 'June'
"account" : "g", "amount" : 80" "day" : 10" month" : "May"
}
How do I find the total amount for each month June and May separately?
dictionary= sum(d["amount"] for d in my_dict)
You can filter which elements to sum, by adding an if statement at the end of the one-liner for-loop:
sum(d['amount'] for d in my_dict if d['month'] == month)
Then, we can wrap this line of code inside a small function to compute the results for May and June:
my_dict = [{'account': 'x*', 'amount': 300, 'day': 3, 'month': 'June'},
{'account': 'y*', 'amount': 550, 'day': 9, 'month': 'May' },
{'account': 'z*', 'amount': -200, 'day': 21, 'month': 'June'},
{'account': 'g' , 'amount': 80, 'day': 10, 'month': 'May' }]
get_sum = lambda my_dict, month: sum(d['amount'] for d in my_dict if d['month'] == month)
sum_June = get_sum(my_dict, 'June')
sum_May = get_sum(my_dict, 'May' )
print('sum_June:', sum_June)
# sum_June: 100
print('sum_May :', sum_May)
# sum_May : 630
PS. Initially, the dictionary my_dict was over-writting data, because everything was stored in the same object. In the code above, my_dict is split into a list with multiple rows to avoid this issue. Please consider this methodology to store data in your project - it is very common.
Related
I have this dictionary, and when I code for it, I only have the answer for June, May, September. How would I code for the months that are not given in the dictionary? Obviously, I have zero for them.
{'account': 'Amazon', 'amount': 300, 'day': 3, 'month': 'June'}
{'account': 'Facebook', 'amount': 550, 'day': 5, 'month': 'May'}
{'account': 'Google', 'amount': -200, 'day': 21, 'month': 'June'}
{'account': 'Amazon', 'amount': -300, 'day': 12, 'month': 'June'}
{'account': 'Facebook', 'amount': 130, 'day': 7, 'month': 'September'}
{'account': 'Google', 'amount': 250, 'day': 27, 'month': 'September'}
{'account': 'Amazon', 'amount': 200, 'day': 5, 'month': 'May'}
The method I used for months mentioned in the dictionary:
year_balance=sum(d["amount"] for d in my_dict) print(f"The total year balance is {year_balance} $.")
import calendar
months = calendar.month_name[1:]
results = dict(zip(months, [0]*len(months)))
for d in data:
results[d["month"]] += d["amount"]
# then you have results dict with monthly amounts
# sum everything to get yearly total
total = sum(results.values())
This might help:
from collections import defaultdict
mydict = defaultdict(lambda: 0)
print(mydict["January"])
Also, given the comments you have written, is this what you are looking for?
your_list_of_dicts = [
{"January": 3, "March": 5},
{"January": 3, "April": 5}
]
import calendar
months = calendar.month_name[1:]
month_totals = dict()
for month in months:
month_totals[month] = 0
for d in your_list_of_dicts:
month_totals[month] += d[month] if month in d else 0
print(month_totals)
{'January': 6, 'February': 0, 'March': 5, 'April': 5, 'May': 0, 'June': 0, 'July': 0, 'August': 0, 'September': 0, 'October': 0, 'November': 0, 'December': 0}
You can read the following blog regarding the usage of dictionaries and how to perform calculations.
5 best ways to sum dictionary values in python
This is on of the examples given in the blog.
wages = {'01': 910.56, '02': 1298.68, '03': 1433.99, '04': 1050.14, '05': 877.67}
total = sum(wages.values())
print('Total Wages: ${0:,.2f}'.format(total))
Here is the result with 100,000 records.
Result with 100,000 records
I am getting my time in day and month format like this:
final =[{'day': 29, 'month': 5},{'day': 30, 'month': 5},{'day': 1, 'month': 6},{'day': 2, 'month': 6},{'day': 3, 'month': 6},{'day': 4, 'month': 6},{'day': 5, 'month': 6},{'day': 6, 'month': 6}, {'day': 7, 'month': 6}, {'day': 8, 'month': 6}, {'day': 9, 'month': 6}]
I want to check count of consecutive days in array from today to keep count of last online days . and if like my previous day exist it will add 1 in total count. for example {'day': 5, 'month': 6},{'day': 8, 'month': 6}, {'day': 9, 'month': 6}
in these three record 6 is missing so my count will be 2 .
there is now issue that like if it goes to previous month and there month end is like 30 and month 5 , how I will add this to my count ?
for now : I am doing like this
#getting today day and month and year
today_time = int(time.time())
today_time_day = datetime.datetime.fromtimestamp(today_time)
#to check if previous month day end start
month = monthrange(today_time_day.year, today_time_day.month)
print(month)
i =0
streak = 0
for x in reversed(final):
if today_time_day.day - i == x['day']:
streak += 1
else:
streak = 1
break
i += 1
print(streak)
I am trying to calculate but answer is wrong and not sure how I can use previous month streak .
So the answer is we need to keep track of last month count and reset loop count
today_time = int(time.time())
today_time_day = datetime.datetime.fromtimestamp(today_time)
final =[{'day': 29, 'month': 5},{'day': 28, 'month': 5},{'day': 1, 'month': 6},{'day': 2, 'month': 6},{'day': 3, 'month': 6},{'day': 4, 'month': 6},{'day': 5, 'month': 6},{'day': 6, 'month': 6}, {'day': 7, 'month': 6}, {'day': 8, 'month': 6}, {'day': 9, 'month': 6}]
month = monthrange(today_time_day.year, today_time_day.month)
i =0
current_day = today_time_day.day
streak = 0
for x in reversed(final):
if current_day - i == 0 and today_time_day.month -1 == x["month"] :
current_day = month[1]
i = 0
if current_day - i == x['day']:
streak += 1
else:
break
i += 1
print(streak)
I have to parse the following file in python:
20100322;232400;1.355800;1.355900;1.355800;1.355900;0
20100322;232500;1.355800;1.355900;1.355800;1.355900;0
20100322;232600;1.355800;1.355800;1.355800;1.355800;0
I need to end upwith the following variables (first line is parsed as example):
year = 2010
month = 03
day = 22
hour = 23
minute = 24
p1 = Decimal('1.355800')
p2 = Decimal('1.355900')
p3 = Decimal('1.355800')
p4 = Decimal('1.355900')
I have tried:
line = '20100322;232400;1.355800;1.355900;1.355800;1.355900;0'
year = line[:4]
month = line[4:6]
day = line[6:8]
hour = line[9:11]
minute = line[11:13]
p1 = Decimal(line[16:24])
p2 = Decimal(line[25:33])
p3 = Decimal(line[34:42])
p4 = Decimal(line[43:51])
print(year)
print(month)
print(day)
print(hour)
print(minute)
print(p1)
print(p2)
print(p3)
print(p4)
Which works fine, but I am wondering if there is an easier way to parse this (maybe using struct) to avoid having to count each position manually.
from decimal import Decimal
from datetime import datetime
line = "20100322;232400;1.355800;1.355900;1.355800;1.355900;0"
tokens = line.split(";")
dt = datetime.strptime(tokens[0] + tokens[1], "%Y%m%d%H%M%S")
decimals = [Decimal(string) for string in tokens[2:6]]
# datetime objects also have some useful attributes: dt.year, dt.month, etc.
print(dt, *decimals, sep="\n")
Output:
2010-03-22 23:24:00
1.355800
1.355900
1.355800
1.355900
You could use regex:
import re
to_parse = """
20100322;232400;1.355800;1.355900;1.355800;1.355900;0
20100322;232500;1.355800;1.355900;1.355800;1.355900;0
20100322;232600;1.355800;1.355800;1.355800;1.355800;0
"""
stx = re.compile(
r'(?P<date>(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2}));'
r'(?P<time>(?P<hour>\d{2})(?P<minute>\d{2})(?P<second>\d{2}));'
r'(?P<p1>[\.\-\d]*);(?P<p2>[\.\-\d]*);(?P<p3>[\.\-\d]*);(?P<p4>[\.\-\d]*)'
)
f = [{k:float(v) if 'p' in k else int(v) for k,v in a.groupdict().items()} for a in stx.finditer(to_parse)]
print(f)
Output:
[{'date': 20100322,
'day': 22,
'hour': 23,
'minute': 24,
'month': 3,
'p1': 1.3558,
'p2': 1.3559,
'p3': 1.3558,
'p4': 1.3559,
'second': 0,
'time': 232400,
'year': 2010},
{'date': 20100322,
'day': 22,
'hour': 23,
'minute': 25,
'month': 3,
'p1': 1.3558,
'p2': 1.3559,
'p3': 1.3558,
'p4': 1.3559,
'second': 0,
'time': 232500,
'year': 2010},
{'date': 20100322,
'day': 22,
'hour': 23,
'minute': 26,
'month': 3,
'p1': 1.3558,
'p2': 1.3558,
'p3': 1.3558,
'p4': 1.3558,
'second': 0,
'time': 232600,
'year': 2010}]
Here i stored everything in a list, but you could actually go through the results of finditer line by line if you don't want to store everything in memory.
You can also replace fload and/or int with Decimal if needed
Hi. I am working on web app and I am trying to code a List View for getting data from database to create a table for statistics.
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
created = models.DateTimeField(_('created'), auto_now_add=True, db_index=True)
I have a object called Activity where is 'user' as ForeignKey and 'created' as DateTimeField.
Here you can see my code of List View:
class ActivityCountListView(LoginPermissionRequiredMixin, DisplayListViewMixin, SortingListViewMixin, ListView,):
model = Activity
permission_required = 'directory.list_activity'
displays = ['list', 'table']
paginate_values = [10, 50, 100]
paginate_by_display = {'table': paginate_values, 'list': paginate_values}
sorting_options = {'-created': _('Newest'), 'created': _('Oldest'), '-modified': _("Recently modified")}
def get_queryset(self):
queryset = self.filter.qs.select_related('user')
return self.sort_queryset(queryset)
def dispatch(self, request, *args, **kwargs):
self.filter = ActivityFilter(request.user, request.GET, queryset=self.get_whole_queryset())
return super(ActivityCountListView, self).dispatch(request, *args, **kwargs)
def get_whole_queryset(self):
return Activity.objects.restrict_user(self.request.user)
def get_context_data(self, **kwargs):
context_data = super(ActivityCountListView, self).get_context_data(**kwargs)
context_data['filter'] = self.filter
activities = Activity.objects \
.annotate(day=ExtractDay('created'), month=ExtractMonth('created'), year=ExtractYear('created'))\
.values('user', 'day', 'month', 'year') \
.order_by('user')\
data = self.get_data(activities)
context_data.update({
'data': data
})
return context_data
def get_data(self, activities):
data = {}
for activities_data in activities:
print(activities_data)
user = activities_data['user']
day = activities_data['day']
month = activities_data['month']
year = activities_data['year']
dt = datetime(year, month, day).date()
formatted_date = str(dt)
data.update({user: dict()})
data[user][formatted_date] = 1
print(data.keys())
print(data.values())
print(data)
return data
using this code I get print response like this:
print print(activities_data):
{'user': 549, 'day': 24, 'month': 7, 'year': 2018}
{'user': 350, 'day': 24, 'month': 7, 'year': 2018}
{'user': 746, 'day': 31, 'month': 7, 'year': 2018}
{'user': 1, 'day': 31, 'month': 7, 'year': 2018}
{'user': 1, 'day': 24, 'month': 7, 'year': 2018}
{'user': 1, 'day': 24, 'month': 7, 'year': 2018}
{'user': 526, 'day': 31, 'month': 7, 'year': 2018}
{'user': 526, 'day': 24, 'month': 7, 'year': 2018}
{'user': 109, 'day': 24, 'month': 7, 'year': 2018}
{'user': 419, 'day': 24, 'month': 7, 'year': 2018}
print(data.keys()):
dict_keys([549, 350, 746, 1, 526, 109, 419])
print(data.values()):
dict_values([{'2018-07-24': 1}, {'2018-07-24': 1}, {'2018-07-31': 1}, {'2018-07-24': 1}, {'2018-07-24': 1}, {'2018-07-24': 1}, {'2018-07-24': 1}])
print(data):
{549: {'2018-07-24': 1}, 350: {'2018-07-24': 1}, 746: {'2018-07-31': 1}, 1: {'2018-07-24': 1}, 526: {'2018-07-24': 1}, 109: {'2018-07-24': 1}, 419: {'2018-07-24': 1}}
... but it's not like I want to have because for same user there is only one date and there is not count for activities... I expect response like that:
{549: {'2018-07-24': 1}, 350: {'2018-07-24': 1}, 746: {'2018-07-31': 1}, 1: {'2018-07-24': 2, '2018-07-31': 1,}, 526: {'2018-07-24': 1, '2018-07-31: 1}, 109: {'2018-07-24': 1}, 419: {'2018-07-24': 1}}
For better understanding:
If there is more than one activity for same user (like user id 1):
{'user': 1, 'day': 31, 'month': 7, 'year': 2018}
{'user': 1, 'day': 24, 'month': 7, 'year': 2018}
{'user': 1, 'day': 24, 'month': 7, 'year': 2018}
I expect data response like this :
1: {'2018-07-24': 2, '2018-07-31': 1,},
and not just like this:
1: {'2018-07-24': 1},
I really don't know how to do it. I would be so glad to you if you help me and write me what to change and what add to code.... THANK YOU SO MUCH
Use itertools.groupby
>>> activities_lst = [{'user': 549, 'day': 24, 'month': 7, 'year': 2018}, {'user': 350, 'day': 24, 'month': 7, 'year': 2018}, {'user': 746, 'day': 31, 'month': 7, 'year': 2018}, {'user': 1, 'day': 31, 'month': 7, 'year': 2018}, {'user': 1, 'day': 24, 'month': 7, 'year': 2018}, {'user': 1, 'day': 24, 'month': 7, 'year': 2018}, {'user': 526, 'day': 31, 'month': 7, 'year': 2018}, {'user': 526, 'day': 24, 'month': 7, 'year': 2018}, {'user': 109, 'day': 24, 'month': 7, 'year': 2018}, {'user': 419, 'day': 24, 'month': 7, 'year': 2018}]
>>>
>>> from itertools import groupby
>>> f = lambda x: x['user']
>>> res = {user:['{year}-{month:02}-{day}'.format(**date) for date in date_lst] for user,date_lst in groupby(sorted(activities_lst, key=f), f)}
>>> res = {user:{date:len(list(v)) for date,v in groupby(date_lst)} for user,date_lst in res.items()}
>>>
>>> from pprint import pprint
>>> pprint(res)
{1: {'2018-07-24': 2, '2018-07-31': 1},
109: {'2018-07-24': 1},
350: {'2018-07-24': 1},
419: {'2018-07-24': 1},
526: {'2018-07-24': 1, '2018-07-31': 1},
549: {'2018-07-24': 1},
746: {'2018-07-31': 1}}
Looks like problem is in get_data() call.
in place of this
data[user][formatted_date] = 1
may be need to write as below
if formatted_date in data[user]:
data[user][formatted_date] += 1
else
data[user][formatted_date] = 1
I have a dictionary like that:
{12: {'Soccer': {'value': 31, 'year': 2013}},
23: {'Volley': {'value': 24, 'year': 2012},'Yoga': {'value': 3, 'year': 2014}},
39: {'Baseball': {'value': 2, 'year': 2014},'basket': {'value': 4, 'year': 2012}}}
and i would like to have a dataframe like this:
index column
12 {'Soccer': {'value': 31, 'year': 2013}}
23 {'Volley': {'value': 24, 'year': 2012},'Yoga': {'value': 3, 'year': 2014}}
39 {'Baseball': {'value': 2, 'year': 2014},'basket': {'value': 4, 'year': 2012}}
with each nested dictionary set in a unique column, with the row given by the key of the external dictionary. When I use 'from_dict' with orient parameter equal to index, it considers that keys from the nested dictionaries are the labels of the columns and it makes a square dataframe instead of a single column...
Thanks a lot
Use:
df = pd.DataFrame({'column':d})
Or:
df = pd.Series(d).to_frame('column')
print (df)
column
12 {'Soccer': {'year': 2013, 'value': 31}}
23 {'Volley': {'year': 2012, 'value': 24}, 'Yoga'...
39 {'Baseball': {'year': 2014, 'value': 2}, 'bask...
In [65]: pd.DataFrame(d.values(), index=d.keys(), columns=['column'])
Out[65]:
column
12 ({'Soccer': {'value': 31, 'year': 2013}}, {'Vo...
23 ({'Soccer': {'value': 31, 'year': 2013}}, {'Vo...
39 ({'Soccer': {'value': 31, 'year': 2013}}, {'Vo...