Reputation: 9844
I'm trying to process a data struct as follows:
dict<ID, actions>
where actions
is a list of dictionaries, and each of them contain two pairs (at least): 'gameCode':value, 'gameTime':value.
So my data is like:
{user1: [{gameCode : 1, gameTime : 1}, {gameCode : 2, gameTime : 2}],
user2: [{gameCode : 1, gameTime : 1}, {gameCode : 2, gameTime : 2}]}
This data come from a log in which each row represents one action.
I have to produce an output as the following:
ID | action | time | action | time ...
I was wondering how could I write these pairs of action/times in a pythonic way, maybe using a list comprehension. This is what I have so far:
event = 'gameCode'
data = 'gameTime'
# Open the .csv file and creates a dict of actions
with open(file_path, 'rb') as csvfile:
spamreader = csv.DictReader(csvfile, delimiter='\t')
for row in spamreader:
# Add an empty list for 'userID' if it is not registered yet in dict
user = row['userID']
actions = Users.get(user, [])
# Delete the 'userID' from the information
del row['userID']
# Add a register of actions for this user
actions.add(row)
# Update its values
users[user] = actions
# Sort each list of actions based on time
for key, value in users.iteritems():
users[key] = sorted(value, key=lambda k: k[data])
# Write a .csv to be consumed by the app
with open('eventsInput.csv', 'w') as csvfile:
csv.writer(csvfile, delimiter=' ')
for key, value in users.iteritems():
actions = [[d[event], d[data]] for d in value]
writer.writerow([key, 0, 0, 0, 0, [action for action in actions]])
I'm stuck at this last line.
With this, I get this output:
L11-13 0 0 0 0 "[['1002', '358']]"
But I don't want nothing but 1002 358 (i.e., no " , ' [ etc)
Upvotes: 0
Views: 359
Reputation: 9844
After some researcher and a lot of trials, I found out that I can accomplish what I want with this piece of code:
with open('eventsInput.csv', 'w') as csvfile:
writer = csv.writer(csvfile, delimiter='\t')
for key, value in users.iteritems():
# That was what changed the result
actions = list(chain.from_iterable((d[event], d[data]) for d in value))
print actions
writer.writerow([key, 0, 0, 0, 0] + [action for action in actions])
Just don't know why I can't do:
actions = [chain.from_iterable((d[event], d[data]) for d in value)]
Upvotes: 1
Reputation: 30278
To fix your updated code, you can just add lists:
writer.writerow([key, 0, 0, 0, 0] + [action for action in actions]])
But this may cause issues on read because you may have variable number of fields per row, unless len(actions)
is a constant.
Upvotes: 0
Reputation: 30278
Unfortunately you can't have multiple fieldnames with the same value in a DictWriter, you could revert to a normal csv writer (though you might have to deal with uneven lengths of action time tuples for a specific id) or consider that for any id you have a list of actions and a list of times:
from csv import DictWriter
data = [{'id': 1, 'actions':[1,2,3], 'times': [1,2,3]},
{'id': 2, 'actions':[4,5,6], 'times': [4,5,6]}]
with open('fred.csv', 'w+') as f:
writer = DictWriter(f, ['id', 'actions', 'times'])
writer.writeheader()
writer.writerows(data)
fred.csv
id,actions,times
1,"[1, 2, 3]","[1, 2, 3]"
2,"[4, 5, 6]","[4, 5, 6]"
When you read it in, you can zip actions and times to get them back together.
Upvotes: 1