Write a column next to list in csv_python - python

I have two lists, when I print them separately using:
writer.writerows(list_)
I get
list_1:
0 -0.00042 0.004813 0.010428 0.051006
1 0.000053 0.004531 0.010447 0.051962
2 0.000589 0.004518 0.009801 0.052226
3 0.000083 0.004581 0.010362 0.052288
4 -0.000192 0.003726 0.011258 0.051094
5 0.000281 0.004078 0.01008 0.052156
list_2:
-0.000419554 -0.000366128 0.000223134 0.000306416 0.000114709
It's been a whole day I've been trying to add list_2 as another column to list_1 and write them to a csv file. I thought it was straightforward but have stuck. I appreciate any help.

A general solution which combines columns from two lists of lists (or other iterables):
import csv
import itertools
import sys
def combine_columns(iterable1, iterable2):
for x, y in itertools.izip(iterable1, iterable2):
yield list(x) + list(y)
list1 = [[11, 12, 13], [21, 22, 23]]
list2 = [[14, 15], [24, 25]]
writer = csv.writer(sys.stdout)
writer.writerows(combine_columns(list1, list2))
Output:
11,12,13,14,15
21,22,23,24,25

Here is an example, not knowing what your data look like, so I have to guess:
list_1 = [
[1,2,3],
[4,5,6],
[7,8,9],
]
list_2 = [10,20,30]
list_1 = [row + [col] for row, col in zip(list_1, list_2)]
for row in list_1:
print row
Output:
[1, 2, 3, 10]
[4, 5, 6, 20]
[7, 8, 9, 30]
Now that list_1 has list_2 as a new column, you can use the csv module to write it out.

Related

Split a numpy array into 8-elements arrays and invert each of them

Well, I have a numpy array like that:
a=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
My desired output is:
b=['87654321','161514131211109','2423222120191817']
For it, I need first to split "a" into arrays of 8 elements and then I have a list like that:
np.split(a) = [array([1, 2, 3, 4, 5, 6, 7, 8], dtype=int8),
array([9, 10, 11, 12, 13, 14, 15, 16], dtype=int8),
array([17, 18, 19, 20, 21, 22, 23, 24], dtype=int8)]
so, I need to invert each array into it and join the numbers to make like a list of joint numbers.
No need for numpy, though it will work for an array as well. One way:
>>> [''.join(str(c) for c in a[x:x+8][::-1]) for x in range(0, len(a), 8)]
['87654321', '161514131211109', '2423222120191817']
Try this. You reshape your data and then convert it to string elements. Loop it and append it to new list.
import numpy as np
a=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
lst = list(np.array(a).reshape(3,8).astype("U"))
my_lst = []
for i in lst:
my_lst.append("".join(i[::-1]))
print(my_lst)
The simplest way is first to reverse the original array (or create a reversed copy), and then to split:
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
acopy = a[::-1]
splitted = np.array_split(acopy, 3)
print(splitted[0]) # [24 23 22 21 20 19 18 17]
print(splitted[1]) # [16 15 14 13 12 11 10 9]
print(splitted[2]) # [8 7 6 5 4 3 2 1]
Now when lists are reversed, you can join elements of each list to make strings:
str1 = ''.join(str(x) for x in splitted[0]) # '2423222120191817'
str2 = ''.join(str(x) for x in splitted[1]) # '161514131211109'
str3 = ''.join(str(x) for x in splitted[2]) # '87654321'

For loop resulting in wrong output

The code snippet below results in [5,7,18,23,50], why 5 is not getting removed from the resultant list?
list1 = [11, 5, 17, 18, 23, 50]
not_needed = {11, 5}
for e in list1:
if e in not_needed:
list1.remove(e)
else:
pass
print(list1)
Because you are modifying the list as it is being iterated over.
When you read the first item, it is 11 so it gets removed.
When you read the second item, it is 17, because the first item
was removed. The item 5 is now the new first item and you never get
to check it.
Because once the 11 is removed, the 5 gets skipped during iteration. This is why you never iterate over a list and remove from it at the same time.
list1 = [11, 5, 17, 18, 23, 50]
not_needed = {11, 5}
for e in not_needed:
list1.remove(e)
print(list1)
Gives:
[17, 18, 23, 50]
Use list comprehension when looping over a list and modifying it at the same time.
list1 = [x for x in list1 if not x in not_needed]
list1
[17, 18, 23, 50]
Further details on this here:
https://www.analyticsvidhya.com/blog/2016/01/python-tutorial-list-comprehension-examples/
This is because after first iteration item 11 is deleted and it goes for second index which becomes 17 in list [5,17,18,23,50]
The best way to rectify this is to take result list so that you dont have to mutate "list1"
list1 = [11, 5, 17, 18, 23, 50]
not_needed = {11, 5}
result = []
for e in list1:
if e in not_needed:
pass
else:
result.append(e)
print(result)
for loop in python runs on the indexes not on each element.
When it finds 11 and removes it from list1, list1 becomes [5, 17, 18, 23, 50] but the loop is now on second element. So it misses 5 in the list.

How to replace an item in a list depending on an item in another list?

I have two equal lists, their values are connected to each other:
list1 = [29, 4, 15, 4, 5, 5]
list2 = [57.49999999999999, 89.74358974358975, 78.94736842105263, 100.0, 94.44444444444444, 57.89473684210527]
How do I change the i-th value in list1 to 40 if the corresponding i-th value in list2 is less than 65.0?
You should use zip as I wrote in a comment, I think that would be the cleanest solution.
new_list1 = []
for a, b in zip(list1, list2):
if b < 65.0:
new_list1.append(40)
else:
new_list1.append(a)
A list comprehension with the ternary operator and zip should do the trick:
[40 if list2_val < 65.0 else list1_val
for list1_val, list2_val in zip(list1, list2)]
Out[2]: [40, 4, 15, 4, 5, 40]
FWIW, this more compact (but perhaps more difficult to read) syntax will produce an identical result to that of Tobias's answer.
Depending on how long your lists are, you might try using pandas and numpy:
>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({'list1': list1, 'list2': list2})
>>> df
list1 list2
0 29 57.500000
1 4 89.743590
2 15 78.947368
3 4 100.000000
4 5 94.444444
5 5 57.894737
>>> df['list1_new'] = np.where(df['list2'] < 65, 40, df['list1'])
list1 list2 list1_new
0 29 57.500000 40
1 4 89.743590 4
2 15 78.947368 15
3 4 100.000000 4
4 5 94.444444 5
5 5 57.894737 40
You have to iterate on list2 to find which index has a value smaller than 65.0. With this index number you can replace nth value in list1:
list1 = [29, 4, 15, 4, 5, 5]
list2 = [57.49999999999999, 89.74358974358975, 78.94736842105263, 100.0,
94.44444444444444, 57.89473684210527]
for i in range(0, len(list1)):
if list2[i] < 65.0:
list1[i] = 40
print(list1)

Convert string of list to list

I have the list of strings:
['[12 9 15]','[98 12 18]','[56 45 45]']
and I want to convert it to
[[12,9,15],[98,12,18],[56,45,45]]
You can use split inside a list comprehension to do this.
As [1 2 3] is not the proper representation of a python list in a string, we can remove the brackets to get '1 2 3' which on splitting becomes ['1', '2', '3']. This can be easily converted to a integer nested list by casting it to an int using the int callable.
>>> l = ['[12 9 15]','[98 12 18]','[56 45 45]']
>>> [[int(j) for j in i[1:-1].split()] for i in l]
[[12, 9, 15], [98, 12, 18], [56, 45, 45]]
For further reading What does "list comprehension" mean? How does it work and how can I use it?
Your strings [12 9 15] aren't formatted like python lists (commas are missing). You've got a couple options depending on how robust your parser needs to be:
import ast
out_list = []
for string_list in list_of_strings:
list_repr = ','.join(string_list.split())
out_list.append(ast.literal_eval(list_repr))
This will work so long as you don't have any inner strings formatted like:
'[ 12 9, 5] (the leading space will mess it up)
I think that probably the most robust parser that I can think of is to remove the [ and ] and them parse it yourself:
out_list = []
for string_list in list_of_strings:
str_items = string_list.replace('[', '').replace(']', '')
out_list.append([int(item) for item in str_items.split()])
As long as the strings are fairly regular, this should work:
>>> x = ['[12 9 15]','[98 12 18]','[56 45 45]']
>>> x = [[int(i) for i in string.strip('[]').split()] for string in x]
>>> x
[[12, 9, 15], [98, 12, 18], [56, 45, 45]]
Use a regular expression
[map(int, re.findall('\d+', item)) for item in x]
In case it is not always well-formated.
>>> import re
>>> [map(int, re.findall('\d+', item)) for item in x]
[[12, 9, 15], [98, 12, 18], [56, 45, 45]]
The simpler the solution, the better it is for others to understand.
Well here is my solution:
list_of_strings = ['[12 9 15]','[98 12 18]','[56 45 45]']
list_of_lists = [map(int, x[1:-1].split()) for x in list_of_strings]
So I using list-comprehension here. The 'map' function returns a list. The code x[1:-1].split() will split each string on space character(s) and the each string token would then be converted to 'int' which is the function I've passed to the map function.
Need more explanation over my code?
Please check if this is helpful.
>>> x = ['[12 9 15]','[98 12 18]','[56 45 45]']
>>> print eval(str([ item.replace(" ",",") for item in x ]).replace("'", ''))
[[12, 9, 15], [98, 12, 18], [56, 45, 45]]

Python Subtract Arrays Based on Same Time

Is there a way I can subtract two arrays, but making sure I am subtracting elements that have the same day, hour, year, and or minute values?
list1 = [[10, '2013-06-18'],[20, '2013-06-19'], [50, '2013-06-23'], [15, '2013-06-30']]
list2 = [[5, '2013-06-18'], [5, '2013-06-23'] [20, '2013-06-25'], [20, '2013-06-30']]
Looking for:
list1-list2 = [[5, '2013-06-18'], [45, '2013-06-23'] [10, '2013-06-30']]
How about using a defaultdict of lists?
import itertools
from operator import sub
from collections import defaultdict
def subtract_lists(l1, l2):
data = defaultdict(list)
for sublist in itertools.chain(l1, l2):
value, date = sublist
data[date].append(value)
return [(reduce(sub, v), k) for k, v in data.items() if len(v) > 1]
list1 = [[10, '2013-06-18'],[20, '2013-06-19'], [50, '2013-06-23'], [15, '2013-06-30']]
list2 = [[5, '2013-06-18'], [5, '2013-06-23'], [20, '2013-06-25'], [20, '2013-06-30']]
>>> subtract_lists(list1, list2)
[(-5, '2013-06-30'), (45, '2013-06-23'), (5, '2013-06-18')]
>>> # if you want them sorted by date...
>>> sorted(subtract_lists(list1, list2), key=lambda t: t[1])
[(5, '2013-06-18'), (45, '2013-06-23'), (-5, '2013-06-30')]
Note that the difference for date 2013-06-30 is -5, not +5.
This works by using the date as a dictionary key for a list of all values for the given date. Then those lists having more than one value in its list are selected, and the values in those lists are reduced by subtraction. If you want the resulting list sorted, you can do so using sorted() with the date item as the key. You could move that operation into the subtract_lists() function if you always want that behavior.
I think this code does what you want:
list1 = [[10, '2013-06-18'],[20, '2013-06-19'], [50, '2013-06-23'], [15, '2013-06-30']]
list2 = [[5, '2013-06-18'], [5, '2013-06-23'], [20, '2013-06-25'], [20, '2013-06-30']]
list1=dict([[i[1],i[0]] for i in list1])
list2=dict([[i[1],i[0]] for i in list2])
def minus(a,b):
return { k: a.get(k, 0) - b.get(k, 0) for k in set(a) & set(b) }
minus(list2,list1)
# returns the below, which is now a dictionary
{'2013-06-18': 5, '2013-06-23': 45, '2013-06-30': 5}
# you can convert it back into your format like this
data = [[value,key] for key, value in minus(list1,list2).iteritems()]
But you seem to have an error in your output data. If you want to include data when it's in either list, define minus like this instead:
def minus(a,b):
return { k: a.get(k, 0) - b.get(k, 0) for k in set(a) | set(b) }
See this answer, on Merge and sum of two dictionaries, for more info.

Categories

Resources