27

I am trying read a file and split a cell in each line by a comma and then display only the first and the second cells which contain information regarding the latitude and the longitude. This is the file:

time,latitude,longitude,type2015-03-20T10:20:35.890Z,38.8221664,-122.7649994,earthquake2015-03-20T10:18:13.070Z,33.2073333,-116.6891667,earthquake2015-03-20T10:15:09.000Z,62.242,-150.8769,earthquake

My program:

def getQuakeData():
    filename = input("Please enter the quake file: ")
    readfile = open(filename, "r")
    readlines = readfile.readlines()

    Type = readlines.split(",")
    x = Type[1]
    y = Type[2]
    for points in Type:
        print(x,y)
getQuakeData()

When I try to execute this program, it gives me an error

"AttributeError: 'list' object has no attribute 'split'

Please help me!

unor
  • 92,415
  • 26
  • 211
  • 360
loveTrumpsHate
  • 601
  • 3
  • 11
  • 15
  • 2
    Because `list` has no `split()` only `string` objects have `split` – letsc May 05 '15 at 00:31
  • 3
    `readlines()` returns a `list`. You have to use `split()` on each string in that `list`. – TigerhawkT3 May 05 '15 at 00:32
  • Read the error closely. You are trying split `readlines`, which is a list. That cannot be done. – Loocid May 05 '15 at 00:32
  • Why are you using `readlines` in the first place? If you just want the first line as one string, that's `readline`. If you want the whole file as one giant string, that's `read`. If you want a list or other iterable of lines, you _can_ use `readlines` for that, but you can also just use the file itself, so it's still not useful. – abarnert May 05 '15 at 00:33
  • 1
    As a side note, you might want to consider using the `csv` module here. Especially if there's actually a header line; then you could use `for row in csv.DictReader(readfile):` and then your values are `row['latitude']` and `row['longitude']` instead of `row[1]` and `row[2]`, which might be more readable. – abarnert May 05 '15 at 00:47

3 Answers3

33

I think you've actually got a wider confusion here.

The initial error is that you're trying to call split on the whole list of lines, and you can't split a list of strings, only a string. So, you need to split each line, not the whole thing.

And then you're doing for points in Type, and expecting each such points to give you a new x and y. But that isn't going to happen. Types is just two values, x and y, so first points will be x, and then points will be y, and then you'll be done. So, again, you need to loop over each line and get the x and y values from each line, not loop over a single Types from a single line.

So, everything has to go inside a loop over every line in the file, and do the split into x and y once for each line. Like this:

def getQuakeData():
    filename = input("Please enter the quake file: ")
    readfile = open(filename, "r")

    for line in readfile:
        Type = line.split(",")
        x = Type[1]
        y = Type[2]
        print(x,y)

getQuakeData()

As a side note, you really should close the file, ideally with a with statement, but I'll get to that at the end.


Interestingly, the problem here isn't that you're being too much of a newbie, but that you're trying to solve the problem in the same abstract way an expert would, and just don't know the details yet. This is completely doable; you just have to be explicit about mapping the functionality, rather than just doing it implicitly. Something like this:

def getQuakeData():
    filename = input("Please enter the quake file: ")
    readfile = open(filename, "r")
    readlines = readfile.readlines()
    Types = [line.split(",") for line in readlines]
    xs = [Type[1] for Type in Types]
    ys = [Type[2] for Type in Types]
    for x, y in zip(xs, ys):
        print(x,y)

getQuakeData()

Or, a better way to write that might be:

def getQuakeData():
    filename = input("Please enter the quake file: ")
    # Use with to make sure the file gets closed
    with open(filename, "r") as readfile:
        # no need for readlines; the file is already an iterable of lines
        # also, using generator expressions means no extra copies
        types = (line.split(",") for line in readfile)
        # iterate tuples, instead of two separate iterables, so no need for zip
        xys = ((type[1], type[2]) for type in types)
        for x, y in xys:
            print(x,y)

getQuakeData()

Finally, you may want to take a look at NumPy and Pandas, libraries which do give you a way to implicitly map functionality over a whole array or frame of data almost the same way you were trying to.

abarnert
  • 354,177
  • 51
  • 601
  • 671
2

The problem is that readlines is a list of strings, each of which is a line of filename. Perhaps you meant:

for line in readlines:
    Type = line.split(",")
    x = Type[1]
    y = Type[2]
    print(x,y)
ODiogoSilva
  • 2,394
  • 1
  • 19
  • 20
0

what i did was a quick fix by converting readlines to string but i do not recommencement it but it works and i dont know if there are limitations or not

def getQuakeData():
    filename = input("Please enter the quake file: ")
    readfile = open(filename, "r")
    readlines = str(readfile.readlines())

    Type = readlines.split(",")
    x = Type[1]
    y = Type[2]
    for points in Type:
        print(x,y)
getQuakeData()
MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119