How to delete a row from dataframe as python code? - python

I'm having the function delete_employee(self, new_employee) which gets a csv file path and an employee credentials which I want to remove, and suppose to delete him from the file.
My function doesn't delete it and also shows this error:
FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison return op(a, b).
Can you please help me understand why it goes wrong?
class Employee(object):
def __init__(self, employee_id, full_name, phone, age):
self.employee_id = employee_id
self.full_name = full_name
self.phone = phone
self.age = age
class EmployeesList(object):
def __init__(self, list_of_employees):
self.list_of_employees = list_of_employees
def open_and_read_file(self, list_of_employees):
employees_csv_data = pd.read_csv(list_of_employees)
return employees_csv_data
def delete_employee(self, new_employee):
employees_csv_data = self.open_and_read_file(self.list_of_employees)
for row in employees_csv_data.values:
if new_employee.employee_id == str(row[0]):
employees_csv_data = employees_csv_data[employees_csv_data.employee_id != new_employee.employee_id]
print(employees_csv_data)

Related

Program cannot Sort

new to python , trying to learn oops ,
in below code my objective is to sort employee list based on rating but stuck at object not iteratable.
class Employee:
def getfn(self):
self.empid=(input(" enter emp id:"))
self.name=input("enter name:")
self.gender=input("enter emp gender: ")
self.salary=input(" enter emp salary:")
self.rating=int(input("enter rating:"))
empz=[]
class menu:
n=0
def entry(self):
n=int(input(" enter no of employees:"))
i=0
while i<n:
temp_emp=Employee()
temp_emp.getfn()
empz.append(temp_emp)
i+=1
def print_rec(self):
#
print("-id--name--gender--salary--rating--")
for i in empz:
print(i.empid,i.name,i.gender,i.salary,i.rating)
#print(sorted(empz,key=lambda x:x[4]))
def sort_rating(empz):
return empz.rating
sorted_emp=sorted(empz, key= sort_rating)
print(empz)
The design of your Employee class isn't great. Values used as its attributes should be validated before class construction.
You can control the number of employees to be input more easily than asking for a count.
Hopefully this will give a better idea of how this might be done.
class Employee:
def __init__(self, empid, name, gender, salary, rating):
self.empid = empid
self.name = name
self.gender = gender
self.salary = salary
self.rating = rating
def __str__(self):
return f'ID={self.empid}, Name={self.name}, Gender={self.gender}, Salary={self.salary}, Rating={self.rating}'
# common input functions
def getInput(prompt, t=str):
while True:
v = input(f'{prompt}: ')
try:
return t(v)
except ValueError:
print('Invalid input')
def getInt(prompt):
return getInput(prompt, int)
def getFloat(prompt):
return getInput(prompt, float)
# end of common input functions
employeeList = []
while eid := getInput('ID (Enter to finish)'):
name = getInput('Name')
gender = getInput('Gender')
salary = getFloat('Salary')
rating = getInt('Rating')
employeeList.append(Employee(eid, name, gender, salary, rating))
for employee in sorted(employeeList, key=lambda x: x.rating):
print(employee)
The common input functions should be in a separate py file so you can import them when needed rather than re-writing them every time. They're trivial but you'll find them helpful when trying to ensure that input is appropriate

Problems with multiplying a class variable with an instance

I am new to pyhton and also new to working with classes. I am working on the below problem where I want to multiply the class variable (raise_amount) by the instance salary. However, when i do this, I get None as output. I would like to get the salary amount per person multiplied by 1.04. Any help will be greatly appreciated.
class Person:
raise_amount = 1.04
def __init__(self, name, street_name, house_nr, post_code, salary): #:post_code, salary):
self.name = name
self.street_name = street_name
self.house_nr = house_nr
self.post_code = post_code
self.salary = salary
def street_name_and_house_nr(self):
return '{} {}'.format(self.street_name, self.house_nr)
def apply_raise(self): # here is the code that seems to have problems
self.salary = int(Person.raise_amount * self.salary)
def street_name_and_house_nr_salary(self):
return self.name + ' ' + str(self.salary)
prs_1 = Person("Mary's", 'Broadway', 304, '2526 CG', 10)
prs_2 = Person("Jhon's", 'Longstreet', 304, '2829 AK',7)
prs_3 = Person("Larry's", 'Chinstreet', 58, '3046 JP', 8)
print(Person.apply_raise(prs_1))
print(Person.apply_raise(prs_2))
print(Person.apply_raise(prs_3))
This is the output i get when i run the code
None
None
None
apply_raise() doesn't return the new salary, it just updates the salary attribute. So you should get that separately to print it.
prs_1.apply_raise()
print(prs_1.salary)
Other notes:
Conventionally the first argument to methods is self. Don't make up your own name (what does lelf mean?).
You should call methods using instance.method(), not Class.method(instance). This ensures that the proper method will be used when the instance is in a subclass.

Python project help (classes/expected type)

I am working on a project for school, simulating a payroll program, and I am getting an error. The error I am getting is
'Expected type 'Classification', got 'Employee' instead'. The relevant code is (I put *** around the code generating the error, it is the 5th function under the Employee Class).
class Employee:
def __init__(self, emp_id, first_name, last_name, address, city, state, zipcode, clas = None):
self.emp_id = emp_id
self.first_name = first_name
self.last_name = last_name
self.address = address
self.city = city
self.state = state
self.zipcode = zipcode
self.classification = clas
def make_hourly(self, hourly_rate):
self.clas = Hourly(hourly_rate)
self.classification = self.clas
def make_salaried(self, salary):
self.clas = Salaried(salary)
self.classification = self.clas
def make_commissioned(self, salary, rate):
self.clas = Commissioned(rate, salary)
self.classification = self.clas
def issue_payment(self):
***pay = Classification.compute_pay(self)***
print('Mailing', pay, 'to', self.first_name, self.last_name, 'at', self.address, self.city, self.state, self.zipcode)
class Classification(ABC):
''' Interface for employee classifications '''
#abstractmethod
def compute_pay(self):
pass
class Hourly(Classification):
''' Manages timecard info. Computes pay '''
def __init__(self, hourly_rate):
self.hourly_rate = hourly_rate
self.timecards = [] # A list of floats representing hours worked
def compute_pay(self):
for i in list_of_timecards:
if i[0] == self.emp_id:
self.timecards.extend(i[1:])
total = list(map(float, self.timecards))
total = sum(total)
self.timecards.clear()
return total * self.hourly_rate
def add_timecard(self, hours):
self.timecards.append(hours)
class Salaried(Classification):
def __init__(self, salary):
self.salary = salary
def compute_pay(self):
return self.salary / 24
class Commissioned(Salaried):
def __init__(self, salary, commission_rate):
self.commission_rate = commission_rate
self.salary = salary
self.receipts = []
def add_receipt(self, amount):
self.receipts.append(amount)
def compute_pay(self):
for i in list_of_receipts:
if i[0] == self.emp_id:
self.receipts.extend(i[1:])
total = list(map(float, self.receipts))
total = sum(total)
self.receipts.clear()
return (self.salary / 24) + ((self.commission_rate / 100) * total)
My understanding of the problem is that I need to pass my 'employee' object to the 'compute_pay' function, which then passes it to the relevant child class (hourly etc...) to run and return the result. I have tried changing
pay = Classification.compute_pay(self)
to
pay = Classification.compute_pay(self.clas)
however that returns error 'AttributeError: 'Employee' object has no attribute 'clas'
which makes no sense. Maybe it is that I am not assigning the employees to the class correctly?
The code for that is (it pulls from a CSV file, and it is pulling the data correctly and generating the class objects, I have checked)
def load_employees():
f = open("employees.csv")
f.readline() # skip header line
for line in f:
fields = line.strip().split(',')
emp = Employee(*fields[:7])
if fields[7] == '3':
clas = Hourly(fields[10]) # Need to define Hourly
emp.classification = clas
elif fields[7] == '2':
clas = Commissioned(fields[8], fields[9])
emp.classification = clas
elif fields[7] == '1':
clas = Salaried(fields[8])
emp.classification = clas
employees.append(emp)
I will figure out your line Classification.compute_pay(self):
Classification => the class Classification
compute_pay => class
method self => this = an Employee instance
pass means do nothing and is used to avoid unneccessary code.
Every class method has self as an argument to allow refering to this instance of the class.
To pass an argument (here your employee) use a parameter. Also implementing a method of the parent class overrides this method.
Every function compute_pay should have a second argument
def compute_pay(self, employee):
# do your stuff
And then you can use this line in issue_payment
pay = self.clas.compute_pay(self)
Two issues here,
Firstly, your Employee instance has two attributes: clas and classification. However, in your constructor, only classification is set.
def __init__(...
...
self.classification = clas
But self.clas is not set to anything. That's why you are getting that error 'Employee' object has no attribute 'clas'. It is only set when one of the make_hourly, make_salaried, or make_commissioned methods are invoked. So when you load the employees CSV, instead of manually creating the instance like you are doing here
clas = Hourly(fields[10])
you should be calling the method make_hourly on your emp instance, like so
emp.make_hourly(fields[10])
It's worth noting that fields[10] is terrible naming. Instead of unpacking all the fields at once, try to unpack them during the for loop:
for a, b, c, d in csv:
...
Secondly, this line of code is wrong in multiple ways
pay = Classification.compute_pay(self)
compute_pay is not a static function or a classmethod. So it shouldn't be called on the Classification class itself, but the Classification instance. This is what you stored in your self.clas attribute. So, compute_pay should be called on self.clas:
def issue_payment(self):
pay = self.clas.compute_pay()
...
In addition to that, when you call a method of a class from inside of another method in the same class, you don't ever need to pass the self argument. It is implied. So even if compute_pay was static or a class method, which it isn't, it would be called like so,
Classification.compute_pay()
Notice there is no self inside the parentheses. Similarly, when you call another method that is not static, self is never passed as an argument:
def my_method(self):
self.another_method()

Sorting objects using CSV data

Before I start I am noob
So, I made objects using data from a CSV file which was in the form 'doe,john,m,20', which can be seen below:
class FitClinic:
def __init__(self, lname, fname, gender, age):
self.__lname = lname
self.__fname = fname
self.__gender = gender
self.__age = age
def __del__(self):
print("Customer has been deleted")
def set_lname(self):
pass
def get_lname(self):
return self.__lname
def set_fname(self):
pass
def get_fname(self):
return self.__fname
def set_gender(self):
pass
def get_gender(self):
return self.__gender
def set_age(self):
pass
def get_age(self):
return self.__age
fh=open('fit_clinic_20.csv', 'r')
fh.seek(3)
listofcustomers=[]
for row in fh:
c = row.split(",")
listofcustomers.append(FitClinic(c[0], c[1], c[2], c[3:]))
What I need to do is sort these objects by the fname attribute which I have no idea how to do, please help, thanks.
You can use sorted with key
sorted_list=sorted(listofcustomers,key=lambda x: x.get_fname())
Refer to Sorting HOW TO
To check the result, you can just print the information with the method you have implemented:
for x in sorted_list:
print(x.get_fname())
In a more complicated situation, advised by #Maurice Reeves, you can also add __str__ and __repr__ methods.
def __str__(self):
str_to_print=f'lname:{self.__lname},'
str_to_print+=f'fname:{self.__fname},'
str_to_print+=f'gender:{self.__gender},'
str_to_print+=f'age:{self.__age}'
return str_to_print
__repr__=__str__
Then you can print by:
for x in sorted_list:
print(x)
Refer to Python doc.
BTW, you can use pandas to load csv file conveniently.
import pandas
csv_pd=pandas.read_csv('fit_clinic_20.csv')
csv_pd.sort_values(by=['fname']) # If fname is the head of your csv file. If not, just add it.
Refer to pandas.DataFrame.sort_values

Saving from dictionary to file (error)

I'm taking my first Python class so please bear with me, I have ZERO experience in programming but I'm very eager to learn. If you could steer me in the right direction I'd really appreciate it. Thank you in advance.
I've looked through previous questions but I wasn't able to find one that fully helped/explained where I'm getting stuck. I have a dictionary that stores team members(names, phone, jersey) and need to be able to write this to a file. Below is what I currently have, when I run this I get the error AttributeError:'dict' object has no attribute 'getname'.
class Member:
def get name(self):
return self.name
def get phone(self):
return self.phone
def get jersey(self):
return self.jersey
members={}
def saveData(members, filename):
filename=input("Filename to save:")
outFile=open(filename,"wt")
for x in members.keys():
name=members[x].getname
phone=members[x].getphone
jersey=members[x].getjersey
outFile.write(name+","+phone","+jersey+"\n")
print("Data Saved")
outFile.close()
Member class
You've put a space in the function name, so it won't work.
Too, you don't seem to have an __init__ function.
class Member:
def __init__(self, name, phone, jersey):
self.name = name
self.phone = phone
self.jersey = jersey
def get_name(self):
return self.name
def get_phone(self):
return self.phone
def get_jersey(self):
return self.jersey
Anyway, it's a lot easier that just don't make these get functions; the user can get the variables of a class using the dot syntax.
class Member:
def __init__(self, name, phone, jersey):
self.name = name
self.phone = phone
self.jersey = jersey
shell:
>>> member1 = Member("Dave", "123456789", "red")
>>> member.name
'Dave'
>>> member.phone
'123456789'
>>> member.jersey
'red'
saveData function
It won't work, you should do this:
def saveData(members): # don't include filename, it's going to be redefined later
filename = input("Filename to save: ") # space at the end
with open(filename, 'wt') as outFile: # using with for files is recommended
# then you don't need to close the file
for x in members: # you can directly iterate from a dict
name = x.get_name() # you didn't call the function at all
phone = x.get_phone() # members[x] not necessary
jersey = x.get_jersey()
outFile.write(name+", "+phone+", "+jersey+"\n") #missing + sign
print("Data Saved")
Working example
__init__.py
class Member:
def __init__(self, name, phone, jersey):
self.name = name
self.phone = phone
self.jersey = jersey
def get_name(self):
return self.name
def get_phone(self):
return self.phone
def get_jersey(self):
return self.jersey
def saveData(members):
filename = input("Filename to save: ")
with open(filename, 'wt') as outFile:
for x in members:
name = x.get_name()
phone = x.get_phone()
jersey = x.get_jersey()
outFile.write(name+", "+phone+", "+jersey+"\n")
print("Data Saved")
IDLE shell
>>> members = [Member("Dave", "123456789", "red"),
Member("Tom", "133742097", "yellow"),
Member("Elisa", "122333444", "blue"),
Member("John", "987654321", "blue")
]
>>> saveData(members)
Filename to save: output.txt
Data Saved
output.txt
Dave, 123456789, red
Tom, 133742097, yellow
Elisa, 122333444, blue
John, 987654321, blue
You can define getname, getphone in your Member class as follows:
class Member:
def getname(self):
return self.name
def getphone(self):
return self.phone
def getjersey(self):
return self.jersey
Then you can get values from getters in your saveData function :
name=members[x].getname()
phone=members[x].getphone()
jersey=members[x].getjersey()

Categories

Resources