0

I know this question has been asked before, but I think this context is a little different because I'm running into a different problem, where I get a TypeError that list indices must be integers, not tuples.

The code I have right now:

writer = csv.writer(open("test-new.csv", "wb"))
with open("test.csv", "r") as f:
    reader = csv.reader(f)
    for v in reader:
        # does things
        writer.writerow(v[0, 3])

I think this problem is happening because the script thinks I'm trying to write a tuple to a new csv file (test-new), when really I'm just trying to write those two values from the list of 4 values to a new csv.

Any ideas on how to tell python I'm not trying to write a tuple? Is it possible to do this using dictwriter instead, possibly?

If my initial csv was like:

a, b, c, d
1, 2, 3, 4
5, 6, 7, 8

I would want my final output to look like:

a, d
1, 4
5, 8

Thanks!

Nick
  • 109
  • 1
  • 8

4 Answers4

2

Change writer.writerow(v[0, 3]) to writer.writerow(tuple(v[::3])) or writer.writerow((v[0], v[3])).

[::#] is known as extended slice notation, and says to grab elements every # slots, so in this case: 0,3. NB: If your list is longer than four, the first method will give: (v[0],v[3],v[6],...).

Your v[0,3] is not valid Python notation. The interpreter thinks you're trying to pass a tuple to index the list, which cannot be done. Hence the error.

Steve P.
  • 14,489
  • 8
  • 42
  • 72
  • Cool, this worked. Does that work because it first converts the two values from v into a tuple, so that writerow can handle it properly? I'm pretty new to programming, so I want to make sure I understand why everything is going on. Edit: nevermind, you clarified in your post and it all makes sense now. – Nick Dec 07 '13 at 08:02
  • 1
    This works because of "slicing". http://stackoverflow.com/questions/509211/pythons-slice-notation – steveha Dec 07 '13 at 08:03
  • @Nick `(val,val1)` explicitly creates a `tuple`, if you're referring to the second way to do it. – Steve P. Dec 07 '13 at 08:03
1

Replace the v[0,3] with (v[0], v[3]). You are trying to make a non-contiguous slice but without really using slice syntax there. Unless there is a strict pattern you haven't specified, this would be the general way to convert arbitrary elements of a list into a tuple for use where a sequence is expected.

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
0

I know you're working with a particular module but pandas is awesome for csv tables. Check this out:

>>> df = pd.read_csv('test.csv',sep=r'\s+')
>>> df
   a,  b,  c,  d
0  1,  2,  3,  4
1  5,  6,  7,  8
>>> col_list = [0,2]
>>> df = df[col_list] #you just pick which columns you want to keep.
>>> df                #voila
   a,  c,
0  1,  3,
1  5,  7,

If you're feeling experimental you should try it out. (Pretend I chose the columns you needed)

Matt
  • 3,508
  • 6
  • 38
  • 66
0

The issue here is that the syntax you are using to get two items from a list is incorrect. For example:

>>> v = [1, 2, 3, 4]
>>> v[0, 3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not tuple

You can get these values out in several ways. A few approaches are shown below.

For your specific case, you can grab the two items you want:

(v[0], v[3])

You could use a list comprehension:

[v[i] for i in [0, 3]]

You can also use itemgetter from operator:

import operator
operator.itemgetter(0, 3)(v)
David Alber
  • 17,624
  • 6
  • 65
  • 71