0

So I have some csv data all I need from this data is two fields then I will do some calculations using the close price and have two more fields and print those four fields in a certain format.

I was thinking of creating namedtuples with the two fields and then adding the values of the other two fields once I calculate it. Would namedtuples be best to format it to this format, is another option better like dicts or lists?

If using namedtuples is the right way how do I create them with only the two fields from the data and two fields that can have the values added, I was able to create namedtuples but with all the fields by using splitlines() on the data and then creating the namedtuples.

4 Answers4

1

I would use a list of dictionaries. "named tuple" is like a struct or class, thus, you need to what the attributes are when you create a named tuple. Also, because there is no getter/setter method for this special struct, named tuple is immutable. This makes it not flexible for your code. What are you going to do when you want to add or remove an attribute from the named tuple?

In my view, named tuple is just like tuple with the extra merit that making code more readable. Therefore, if tuple is not the data structure for your task, there is no meaning for using named tuple.

// When you only extracts the "DATA" and "CLOSE" attributes, store each row as a dict
d1={"DATE":"2011-11-11", "CLOSE":570.00}
d2={"DATE":"2011-11-12", "CLOSE":580.00}
....
d = [d1, d2]
....
// When you want to add extra attributes to each row, just modify that row
d[0]["INDICATOR"]=560.00
d[1]["SIGNAL"]="SELL"
....
Peng Zhang
  • 3,475
  • 4
  • 33
  • 41
  • 1
    +1. The other advantage of using a list of dictionaries is that you writing (and reading) such a thing in exactly the OP's desired format is trivial with [`csv.DictWriter`](http://docs.python.org/3/library/csv.html#csv.DictWriter) (and `DictReader`). – abarnert Feb 18 '14 at 08:40
  • 1
    @VictorHidrogo: If you've never used dictionaries, see [the tutorial](http://docs.python.org/3/tutorial/datastructures.html#dictionaries). They're a _much_ more basic and fundamental feature than `namedtuple`, which are an advanced thing that you really don't need that often. Your question implies that you don't really understand `namedtuple` any better than `dict` anyway, so you're better off learning `dict` right now. – abarnert Feb 18 '14 at 08:50
0

I was thinking of creating namedtuples with 'date' and 'close' fields with the data and then adding the values of 'indicator' and 'signal' once I calculate it.

You can't.

If you really want attribute-style access, with arbitrary attributes added dynamically, the way to do that is with a plain-old class derived from object. That's exactly what class instances do by default.

What namedtuple adds on top of that is a fixed set of fields, as part of each namedtuple class, where the fields can be accessed by index as well as by name. If you want to add new fields later, you don't want them fixed. So, don't use namedtuple.

However, I don't think you want either attribute access or indexed access; what you really want is keyed access. In other words, a dict.

If you use the csv module in the stdlib instead of trying to use splitlines and parse things manually, this is not just easy, but trivial. For example:

with open('input.csv', 'rb') as f:
    d = list(csv.DictReader(f))

for thing in d:
    # whatever you want, including setting thing['Indicator'], etc.

with open('output.csv', 'wb') as f:
    writer = csv.DictWriter(f, ('Date', 'Close', Indicator', 'Signal').
                            extrasaction='ignore', delimiter='\t')
    writer.writerows(d)
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • @VictorHidrogo: Of course you don't have to create a file. Your question implied that you wanted one, but you've already got the list of dictionaries in `d`, whether you write it out anywhere or not. And you can even use `csv.DictWriter` to write to the screen (via `sys.stdout`) or to an in-memory file like object (via `StringIO`) whose contents you can then `print`, etc. – abarnert Feb 18 '14 at 22:12
0

Use a class... KISS.

class ShareData:

    def __init__(self, date, open_price, high_price, low_price, close_price, 
        volume, adj_close):

        self.date = date
        self.open_price = open_price
        self.high_price = high_price
        self.low_price = low_price
        self.volume = volume
        self.adj_close = adj_close

        # your code to set these here.. or set them None and do it later
        self.indicator = None
        self.signal = None
        return
demented hedgehog
  • 7,007
  • 4
  • 42
  • 49
0

It would be awkward to usenamedtuplesbecause you want to add fields. Dictionaries are very flexible in that regard and the following subclass of one would allow you to access its contents attributes or with the usual indexing[]notation. I got the idea from this SO answer, but it's been around for a while in slightly different forms. Thecsvmodule is the easiest way to read (and write) csv data, so I'd suggest using it rather than parsing the file format yourself.

import csv

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self

with open('input_data.csv', 'rb') as inf:
    data = [AttrDict(d) for d in csv.DictReader(inf)]

for row in data:
    # sample code that creates two new fields
    row.Indicator = float(row.Close) * .80
    row.Signal = "Sell" if row.Indicator > 950.00 else "Buy"

print 'DATE        CLOSE       INDICATOR   SIGNAL'
for item in data:
    print '{:12s}{:12s}{:<12.2f}{:12s}'.format(
            item.Date, item.Close, item.Indicator, item.Signal)

Output:

DATE        CLOSE       INDICATOR   SIGNAL
2014-02-12  1186.69     949.35      Buy
2014-02-11  1190.18     952.14      Sell
2014-02-10  1172.93     938.34      Buy
2014-02-07  1177.44     941.95      Buy
2014-02-06  1159.96     927.97      Buy
2014-02-05  1143.20     914.56      Buy
2014-02-04  1138.16     910.53      Buy
2014-02-03  1133.43     906.74      Buy
Community
  • 1
  • 1
martineau
  • 119,623
  • 25
  • 170
  • 301