2014-02-27 1 views
0

저는 파이썬 기술에 종사하고 있습니다. 다음은 작업중인 데이터의 원시 텍스트 파일입니다. Titanic data파이썬에서 CSV 모듈을 사용하는 데 도움이 필요합니다.

각 행은 한 명을 나타냅니다. 이 파일에는 사람이 생존했는지 여부 (3 번째 열) 등 여러 열이 있습니다. 나는 선상에있는 각 인구 통계의 사람 수 (즉, 남성 수와 여성 수)와 각 그룹의 생존자 수를 계산하려고합니다.

나는 이것을 3 단계로 수행하려고합니다 : 먼저, 해당 사람 (Mr, Mrs, Miss)과 관련된 접두사에 대한 열을 추가하십시오. 그런 다음 정보를 찾을 수있는 열과 해당 열의 가능한 값을 식별하는 함수 get_avg()를 정의하여 grab_values ​​함수에 제공합니다. 세 번째로, grab_values ​​()는 각 그룹의 사람들 수와 생존자 수를 계산합니다.

모두 훌륭하고 멋장이지만 ... 작동하지 않습니다. 카운트와 합계에 대해 0이 계속 유지됩니다. 가능하다면 인쇄 명령을 고집하고 약간의 진전을 시도했지만 여전히해야 할 일을 이해하지 못합니다. 함수가 모든 행 (또는 그 중 어떤 행)에서도 실행되지 않는 것 같은 느낌이 들지만 실제로 그 이유가 무엇인지, 무엇을해야하는지 알지 못합니다.

아무도 도와 줄 수 있습니까?

import csv 

titanic = open('shorttitanic.txt', "rb") 
reader = csv.reader(titanic) 


prefix_list = ["Mr ", "Mrs", "Mis"]  # used to determine if passanger's name includes a prefix 


# There are several demographic details we can count passengers and survivors with, this is a dictionary to map them out along with col number. 
details = {"embarked":[5, "Southampton", "Cherbourg", "Queenstown", ""], 
      "sex":[10, "male","female"], "pclass":[1,"1st","2nd","3rd"], 
      "prefix":[12,"Mr ", "Mrs", "Mis"]}  # first item is col number (starts at 0), other items are the possible values 



# Adding another column for prefix: 
rownum = 0 
for row in reader: 
    # Finding the header: 
    if rownum == 0: 
     header = row 
     header.append("Prefix") 
#  print header 
    else: 
     prefix_location = row[3].find(",") + 2    # finds the position of the comma, the prefix starts after the comma and after a space (+2) 
     prefix = row[3][prefix_location:prefix_location+3] # grabs the 3 first characters of the prefix 
#  print len(prefix), prefix 
     if prefix in prefix_list:       # if there's a prefix in the passanger's name, it's appended to the row 
      if prefix == "Mis": 
       row.append("Miss")       # Mis is corrected to Miss on appending, since we must work with 3 chars 
      else: 
       row.append(prefix) 
     else: 
      row.append("Other/Unknown")      # for cases where there's no prefix in the passanger's name 


#  print len(row), rownum, row[3], prefix, row[11] 
# print row 

    rownum += 1 


# grab_values() will run on all rows and count the number of passengers in each demographic and the number of survivors 
def grab_values(col_num,i): 
    print col_num, "item name", i 
    count = 0 
    tot = 0 
    for row in reader: 
#  print type(row[col_num][0] 
     print row[col_num] 
     if row[col_num] == i: 
      count += 1 
      if row[2] == int(1): 
       tot += 1 
#  print count, tot 
    return count, tot 



# get_avg() finds the column number and possible values of demographic x. 

def get_avg(x):    # x is the category (sex, embarked...) 
    col_num = details[x][0] 
    for i in details[x][1:]: 
     print col_num, i 
#  print type(i) 


     grab_values(col_num,i) 

     count,tot = grab_values(col_num,i) 
     print count,tot 

#  print i, count, tot 



get_avg("sex") 



titanic.close() 

EDIT가 : "접두어": 상기 딕셔너리의 프리픽스 값을 변경 함 [12 "미스터", "부인", "M은"]했다} 할 수있다.

EDIT2 : 여기에 완성 된 코드가 있습니다. 나는 문제의 본질에 관해 warunsl의 조언을 받았다. 그러나 그의 해결책은 적어도 변경을했을 때 작동하지 않았다. 그래서 다른 사람들이이 스레드를 발견하고 시도 할 수있는 경우를 대비하여 올바른 솔루션으로 선택할 수 없다. 그것으로부터 배우기. 도우미 덕분에 많은!

import csv 

titanic = open('titanic.txt', "rb") 
reader = csv.reader(titanic) 


prefix_list = ["Mr ", "Mrs", "Mis"]  # used to determine if passanger's name includes a prefix. Using 3 chars because of Mr. 


# There are several demographic details we can count passengers and survivors with, this is a dictionary to map them out along with col number. 
details = {"embarked":[5, "Southampton", "Cherbourg", "Queenstown", ""], 
      "sex":[10, "male","female"], "pclass":[1,"1st","2nd","3rd"], 
      "prefix":[11,"Mr ", "Mrs", "Miss", "Unknown"]}  # first item is col number (starts at 0), other items are the possible values 

# try to see how the prefix values can be created by using 11 and a refernce to prefix_list 


# Here we'll do 2 things: 
# I - Add another column for prefix, and - 
# II - Create processed_list with each of the rows in reader, since we can only run over reader once, 
# and since I don't know much about handling CSVs or generator yet we'll run on the processed_list instead 

processed_list = [] 
rownum = 0 
for row in reader: 
    # Finding the header: 
    if rownum == 0: 
     header = row 
     header.append("Prefix") 
    else: 
     prefix_location = row[3].find(",") + 2    # finds the position of the comma, the prefix starts after the comma and after a space (+2) 
     prefix = row[3][prefix_location:prefix_location+3] # grabs the 3 first characters of the prefix 

     if prefix in prefix_list:       # if there's a prefix in the passanger's name, it's appended to the row 
      if prefix == "Mis": 
       row.append("Miss")       # Mis is corrected to Miss on appending, since we must work with 3 chars 
      else: 
       row.append(prefix) 
     else: 
      row.append("Unknown")       # for cases where there's no prefix in the passanger's name 

    processed_list.append(row) 

    rownum += 1 

# grab_values() will run on all rows and count the number of passengers in each demographic and the number of survivors 
def grab_values(col_num,i): 
# print col_num, "item name", i 
    num_on_board = 0 
    num_survived = 0 
    for row in processed_list: 
     if row[col_num] == i: 
      num_on_board += 1 
      if row[2] == "1": 
       num_survived += 1 
    return num_on_board, num_survived 



# get_avg() finds the column number and possible values of demographic x. 

def get_avg(x):    # x is the category (sex, embarked...) 
    col_num = details[x][0] 
    for i in details[x][1:]: 
     print "Looking for: ", i, "at col num: ", col_num 

     grab_values(col_num,i) 

     num_on_board,num_survived = grab_values(col_num,i) 

     try: 
      proportion_survived = float(num_survived)/num_on_board 
     except ZeroDivisionError: 
      proportion_survived = "Cannot be calculated" 


     print "Number of %s passengers on board: " %i , num_on_board, "\n" \ 
       "Number of %s passengers survived: " %i, num_survived, "\n" \ 
       "Proportion of %s passengers survived: " %i, "%.2f%%" % (proportion_survived * 100), "\n" 



print "Hello! I can calculate the proportion of passengers that survived according to these parameters: \n \ 
Embarked \n Sex \n Pclass \n Prefix", "\n" 

def get_choice(): 
    possible_choices = ["embarked","sex","pclass","prefix"] 
    choice = raw_input("Please enter your choice: ").lower() 
    if choice not in possible_choices: 
     print "Sorry, I can only work with Embarked/Sex/Pclass/Prefix. Please try again." 
     get_choice() 
    return choice 

user_choice = get_choice() 

get_avg(user_choice) 

titanic.close() 
+0

당신이 이제까지 중 기능을 실행하기 전에 전체'reader' 객체를 배기에 for row in reader을 변경'루프가 아무것도하지 않는다 grab_values'. 첫 번째 루프의 'row'에 대한 변경 사항이 지속될 것으로 예상되는 것처럼 보이지만 실제로는 루프의 로컬 변수를 변경 한 다음이를 버리는 것입니다. 각 행을 새 목록에 추가하려고합니다. – geoffspear

+0

접두어는 무엇을 사용하고 있습니까? 각 접두사의 수 또는 남성과 여성의 수를 세고 있습니까? – stmfunk

+0

@stmfunk 나는 좋은 인구 통계학이 접두어로 생존 비율을 볼 수 있다고 생각했다. 기본적으로 이것은 좋은 연습 일뿐입니다. 하나의 변수를 추가하여 기존의 로직에서 추가 할 수 있습니다. – Optimesh

답변

1

당신이 csv.reader에 대한 설명서를 읽을 경우 호출이 반복자 프로토콜을 구현하는 독자 객체를 반환 볼 수 있습니다. 즉, csv.reader 함수는 예상대로 목록이 아닌 생성자를 반환했습니다.

발전기 요소는 한 번만 사용할 수 있습니다. 다시 사용하려면 독자 객체를 다시 초기화해야합니다. 이 answer에는 파이썬 작업에서 생성자에 대한 철저한 설명이 있습니다.

그래서 처음 읽은 다음 다른 목록에 모든 행을 추가하고 나중에이 새 목록을 사용하거나 다시 사용하기 전에 생성기를 다시 초기화 할 수 있습니다. 당신이 for row in reader:이 작업을 수행 할 바로 전에 grab_values에서

: 두 번째 옵션은 당신으로 큰 파일을 읽는 특히 더 나은 방법입니다

titanic = open('titanic.txt', "rb") 
reader = csv.reader(titanic) 

와 코드가 작동합니다.

EDIT : 처음 csv 파일을 읽을 때 각 행을 수정하기 때문에 수정 된 행을 새 목록에 추가하고 grab_values 방법으로 새 ​​목록을 사용해야합니다.당신의 grab_values에서

# Adding another column for prefix: 
processed_list = [] # Declare a new array 
rownum = 0 
for row in reader: 
    if rownum == 0: 
     header = row 
     header.append("Prefix") 
    else: 
     prefix_location = row[3].find(",") + 2 
     prefix = row[3][prefix_location:prefix_location+3] 
     if prefix in prefix_list: 
      if prefix == "Mis": 
       processed_list.append("Miss") #Change this 
      else: 
       processed_list.append(prefix) #Change this 
     else: 
      processed_list.append("Other/Unknown") #Change this 

, 그래서 내부 for row in processed_list

+0

하지만 그는 첫 번째 단계에서 값을 변경하려고하므로 파일을 다시 열어도 도움이되지 않습니다. – geoffspear

+0

맞아, 내 대답은 발전기 객체에 다시 접근하는쪽으로 향하고있다. 오버는 그가 행을 사전 처리하고 있다는 사실을 보았습니다. 답변을 업데이트할까요 – shaktimaan

+0

고마워요. 접두어로는 작동하지 않습니다. 추가 된 열이있는 함수를 호출하는 방법은 무엇입니까? – Optimesh