I've been trying to make grading system with this code but it has no outcome and I get empty lists. What am I doing wrong?
My code:
def grades_data():
import csv
global idlist
global namelist
global finalscorelist
for i in range(len(idlist)):
if int(finalscorelist[i])>=90 and int(finalscorelist[i])<=100:
grades.append("A")
continue
elif int(finalscorelist[i])>=75 and int(finalscorelist[i])<90:
grades.append("B")
continue
elif int(finalscorelist[i])>=60 and int(finalscorelist[i])<75:
grades.append("c")
continue
elif int(finalscorelist[i])>=50 and int(finalscorelist[i])<60:
grades.append("D")
continue
else:
grades.append("F")
print("----------------------------------------------------------------------") #to make a border
print("id\tname\tgrades")
print("----------------------------------------------------------------------") #to make a border
for (idlist,namelist,grades) in zip (idlist,namelist,grades):
print(str(idlist)+"\t"+str(namelist)+"\t\t"+str(grades))
print("----------------------------------------------------------------------") #to make a border
Output:
id name grades
----------------------------------------------------------------------
----------------------------------------------------------------------
You did not detail the layout of your csv file but I imagine it to be something like this.
id,name,score
1,"Steve",90
2,"Jill",92
3,"Billy",100
4,"Sara",75
5,"Bob",80
6,"Julie",89
7,"Wes",60
8,"Andy",74
9,"Jack",59
10,"Greta",50
11,"Wilma",48
Script
import pandas as pd
df = pd.read_csv("scores.csv")
grades = {
"A": (90, 101),
"B": (75, 90),
"C": (60, 75),
"D": (50, 60),
"F": (0, 50),
}
df["grade"] = None
for grade in grades:
idx = df[
df["score"].between(grades[grade][0], grades[grade][1], inclusive="left")
].index
df.loc[idx, "grade"] = grade
print(df)
df.to_csv("grades.csv")
You will need to pip install pandas to your working environment. This script loads the "scores.csv" file from the working directory, creates a grades dictionary, assign an empty grade column, cycles through the grades dictionary assigning the grades based on the grades dictionary and scores, and finally prints the grades dataframe, and saves a grades.csv file.
Related
I'm wondering what appropriate data structure I'm going to use to store information about chemical elements that I have in a text file. My program should
read and process input from the user. If the user enters an integer then it program
should display the symbol and name of the element with the number of protons
entered. If the user enters a string then my program should display the number
of protons for the element with that name or symbol.
The text file is formatted as below
# element.txt
1,H,Hydrogen
2,He,Helium
3,Li,Lithium
4,Be,Beryllium
...
I thought of dictionary but figured that mapping a string to a list can be tricky as my program would respond based on whether the user provides an integer or a string.
You shouldn't be worried about the "performance" of looking for an element:
There are no more than 200 elements, which is a small number for a computer;
Since the program interacts with a human user, the human will be orders of magnitude slower than the computer anyway.
Option 1: pandas.DataFrame
Hence I suggest a simple pandas DataFrame:
import pandas as pd
df = pd.read_csv('element.txt')
df.columns = ['Number', 'Symbol', 'Name']
def get_column_and_key(s):
s = s.strip()
try:
k = int(s)
return 'Number', k
except ValueError:
if len(s) <= 2:
return 'Symbol', s
else:
return 'Name', s
def find_element(s):
column, key = get_column_and_key(s)
return df[df[column] == key]
def play():
keep_going = True
while keep_going:
s = input('>>>> ')
if s[0] == 'q':
keep_going = False
else:
print(find_element(s))
if __name__ == '__main__':
play()
See also:
Finding elements in a pandas dataframe
Option 2: three redundant dicts
One of python's most used data structures is dict. Here we have three different possible keys, so we'll use three dict.
import csv
with open('element.txt', 'r') as f:
data = csv.reader(f)
elements_by_num = {}
elements_by_symbol = {}
elements_by_name = {}
for row in data:
num, symbol, name = int(row[0]), row[1], row[2]
elements_by_num[num] = num, symbol, name
elements_by_symbol[symbol] = num, symbol, name
elements_by_name[name] = num, symbol, name
def get_dict_and_key(s):
s = s.strip()
try:
k = int(s)
return elements_by_num, k
except ValueError:
if len(s) <= 2:
return elements_by_symbol, s
else:
return elements_by_name, s
def find_element(s):
d, key = get_dict_and_key(s)
return d[key]
def play():
keep_going = True
while keep_going:
s = input('>>>> ')
if s[0] == 'q':
keep_going = False
else:
print(find_element(s))
if __name__ == '__main__':
play()
You are right that it is tricky. However, I suggest you just make three dictionaries. You certainly can just store the data in a 2d list, but that'd be way harder to make and access than using three dicts. If you desire, you can join the three dicts into one. I personally wouldn't, but the final choice is always up to you.
weight = {1: ("H", "Hydrogen"), 2: ...}
symbol = {"H": (1, "Hydrogen"), "He": ...}
name = {"Hydrogen": (1, "H"), "Helium": ...}
If you want to get into databases and some QLs, I suggest looking into sqlite3. It's a classic, thus it's well documented.
I am a beginner in python and making an english/norwegian dictionary. I am trying not to have the same english word come more than once when I run the program. I know that this has been answered many times already, but I just can't get the right code for that implemented in the program. I would appreciate very much if someone could implement the right code for that problem. Here is the code so far:
import random
eng_nor = {'one':'en', 'two': 'to', 'three': 'tre', 'four': 'fire', 'five': 'fem', 'six': 'seks', 'seven': 'syv',
'eight': 'åtte', 'nine': 'ni', 'ten': 'ti'}
print()
print('Number of words in the dictionary: ',len(eng_nor))
print()
eng = list(eng_nor.keys())
print('If you want to exit, type 0')
antall_gloser=int(input('How many words do you want to practice?\n '))
if antall_gloser>len(eng_nor):
x=len(eng_nor)
antall_gloser=x
print('We have just ', x, ' words in the dictionary.')
point = 0
for i in range(antall_gloser):
eng_ord = random.choice(eng)
norsk_ord = eng_nor[eng_ord]
user_guess = input('What is the norwegian word of %s?\n' % eng_ord)
if user_guess == 0:
break
elif user_guess == norsk_ord:
point += 1
print('Correct! Your score is %d' % point)
else:
print('Wrong. The norwegian word of {} is {}.'.format(eng_ord, norsk_ord))
print('We are done. Your final score is %d, Thank you.' % point)
An example of an output I get could be like this:
D:\Users\heva\PycharmProjects\test\virtual\Scripts\python.exe D:/Users/heva/PycharmProjects/test/test10.py
Number of words in the dictionary: 10
If you want to exit, type 0
How many words do you want to practice?
3
What is the norwegian word of two?
to
Correct! Your score is 1
What is the norwegian word of two?
to
Correct! Your score is 2
What is the norwegian word of seven?
syv
Correct! Your score is 3
We are done. Your final score is 3, Thank you.
Process finished with exit code 0
As you see in this example, two of the english words are the same.... Any help would be highly appreciated.. Thanks in advance!
You can create a shuffled version of your dictionaries keys:
import random
eng_nor = {'one':'en', 'two': 'to', 'three': 'tre', 'four': 'fire', 'five': 'fem',
'six': 'seks', 'seven': 'syv', 'eight': 'åtte', 'nine': 'ni', 'ten': 'ti'}
eng = list(eng_nor.keys())
random.shuffle(eng) # inplace shuffling
how_much = 5
# take only the first 5 of the shuffled key-list
for key in eng[:how_much]:
value = eng_nor[key]
if input(f"Translate '{key}': ") == value:
print("Correct")
else:
print(f"Wrong. {key} == {value}")
By shuffling the key list, it is guaranteed that each key is still only choosen once. And using list-slicing won't raise an error if you "overstep":
k = [1,2,3,4]
for elem in k[:2000]:
print(k) # prints 1 to 4 each in a new line
You can do the same using random.sample but you need to respect the maximal key count:
how_much = 9999
# reduce k if needed to the maximum length of your keys()
eng2 = random.sample(eng_nor.keys(), k = min(len(eng_nor),how_much) )
I wanted to run my program on all the cores that I have. Here is the code below which I used in my program(which is a part of my full program. somehow, managed to write the working flow).
def ssmake(data):
sslist=[]
for cols in data.columns:
sslist.append(cols)
return sslist
def scorecal(slisted):
subspaceScoresList=[]
if __name__ == '__main__':
pool = mp.Pool(4)
feature,FinalsubSpaceScore = pool.map(performDBScan, ssList)
subspaceScoresList.append([feature, FinalsubSpaceScore])
#for feature in ssList:
#FinalsubSpaceScore = performDBScan(feature)
#subspaceScoresList.append([feature,FinalsubSpaceScore])
return subspaceScoresList
def performDBScan(subspace):
minpoi=2
Epsj=2
final_data = df[subspace]
db = DBSCAN(eps=Epsj, min_samples=minpoi, metric='euclidean').fit(final_data)
labels = db.labels_
FScore = calculateSScore(labels)
return subspace, FScore
def calculateSScore(cluresult):
score = random.randint(1,21)*5
return score
def StartingFunction(prvscore,curscore,fe_select,df):
while prvscore<=curscore:
featurelist=ssmake(df)
scorelist=scorecal(featurelist)
a = {'a' : [1,2,3,1,2,3], 'b' : [5,6,7,4,6,5], 'c' : ['dog', 'cat', 'tree','slow','fast','hurry']}
df2 = pd.DataFrame(a)
previous=0
current=0
dim=[]
StartingFunction(previous,current,dim,df2)
I had a for loop in scorecal(slisted) method which was commented, takes each column to perform DBSCAN and has to calculate the score for that particular column based on the result(but I tried using random score here in example). This looping is making my code to run for a longer time. So I tried to parallelize each column of the DataFrame to perform DBSCAN on the cores that i had on my system and wrote the code in the above fashion which is not giving the result that i need. I was new to this multiprocessing library. I was not sure with the placement of '__main__' in my program. I also would like to know if there is any other way in python to run in a parallel fashion. Any help is appreciated.
Your code has all what is needed to run on multi-core processor using more than one core. But it is a mess. I don't know what problem you trying to solve with the code. Also I cannot run it since I don't know what is DBSCAN. To fix your code you should do several steps.
Function scorecal():
def scorecal(feature_list):
pool = mp.Pool(4)
result = pool.map(performDBScan, feature_list)
return result
result is a list containing all the results returned by performDBSCAN(). You don't have to populate the list manually.
Main body of the program:
# imports
# functions
if __name__ == '__main__':
# your code after functions' definition where you call StartingFunction()
I created very simplified version of your code (pool with 4 processes to handle 8 columns of my data) with dummy for loops (to achieve cpu-bound operation) and tried it. I got 100% cpu load (I have 4-core i5 processor) that naturally resulted in approx x4 faster computation (20 seconds vs 74 seconds) in comparison with single process implementation through for loop.
EDIT.
The complete code I used to try multiprocessing (I use Anaconda (Spyder) / Python 3.6.5 / Win10):
import multiprocessing as mp
import pandas as pd
import time
def ssmake():
pass
def score_cal(data):
if True:
pool = mp.Pool(4)
result = pool.map(
perform_dbscan,
(data.loc[:, col] for col in data.columns))
else:
result = list()
for col in data.columns:
result.append(perform_dbscan(data.loc[:, col]))
return result
def perform_dbscan(data):
assert isinstance(data, pd.Series)
for dummy in range(5 * 10 ** 8):
dummy += 0
return data.name, 101
def calculate_score():
pass
def starting_function(data):
print(score_cal(data))
if __name__ == '__main__':
data = {
'a': [1, 2, 3, 1, 2, 3],
'b': [5, 6, 7, 4, 6, 5],
'c': ['dog', 'cat', 'tree', 'slow', 'fast', 'hurry'],
'd': [1, 1, 1, 1, 1, 1]}
data = pd.DataFrame(data)
start = time.time()
starting_function(data)
print(
'running time = {:.2f} s'
.format(time.time() - start))
I have a reflex test game and have setup a text file that stores the user's name and score with a space in between. How do I sort the text file numerically so that the lowest numbers are at the top and highest at the bottom
E.g
Ben 1.43
Eric 3.53
Steve 7.45
I want to include the 2 decimals places.
Code:
import time
import random
global start
global end
global score
def gameBegin():
print('***************')
print('* Reflex Game *')
print('***************')
print("\nPress Enter as soon as you see the word 'stop'.")
print('Press Enter to Begin')
input()
def gameStart():
global start
global end
time.sleep(random.randint(1,1))
start = time.time()
input('STOP')
end = time.time()
def gameScore():
global start
global end
global score
score=round(end-start,2)
print (score)
def scorePrint():
global score
with open("Leaderboards.txt", "r+") as board:
print (board.read())
def boardEdit():
global score
name = input('Enter Your Name For The Leader Board : ')
board = open ("Leaderboards.txt","a+")
board.write(name )
board.write(" ")
board.write(str(score) )
def boardSort():
#HELP
gameBegin()
gameStart()
gameScore()
scorePrint()
boardEdit()
boardSort()
look at this link https://wiki.python.org/moin/HowTo/Sorting
this will help you with any kind of sort you need.
but to do what you are asking you would need to perform a sort before printing the leaderboard
A simple ascending sort is very easy -- just call the sorted() function. It returns a new sorted list:
sorted([5, 2, 3, 1, 4])
then becomes
[1, 2, 3, 4, 5]
You can also use the list.sort() method of a list. It modifies the list in-place (and returns None to avoid confusion). Usually it's less convenient than sorted() - but if you don't need the original list, it's slightly more efficient.
>>>a = [5, 2, 3, 1, 4]
>>>a.sort()
>>>a
[1, 2, 3, 4, 5]
select = input("Enter what you would like to do (enter 'x' to exit): ")
functions = {"c": calculator, "a": addsubtract, "s": squareroot,
"p": power, "n": arrange, "f": factorial} # storing break or return result in "Invalid Syntax" in the dictionary
#currently I'm doing this:
if select != "x":
functions[select]()
else:
return
I'm trying to minimize code and have been able to do so by storing functions in a dictionary; I'd like to know if there was a workaround/similar way of doing this in case it's not possible using a dictionary.
You can't:
def r():
return 1
def print_hello():
print("HelloWorld")
l = [print_hello, print_hello, print_hello, r, None]
if __name__ == '__main__':
for i in range(10):
print(i, end='')
l[i]()
$ python3 test.py
> 0HelloWorld
> 1HelloWorld
> 2HelloWorld
> 34Traceback (most recent call last):
> File "test.py", line 14, in <module>
> l[i]()
> TypeError: 'NoneType' object is not callable
And it is not a good idea to store functions in a dictionary:
https://www.python.org/dev/peps/pep-0020/
Flat is better than nested.