Using If /Else Statement Operator in Pandas/Python - python

I'm trying to run a section of script that when it read a CSV file it does what the script says.
This is the code rn:
x = input("Do you want to run a mini campaign? Type y for yes or n for no: ")
x = x.lower().strip()
if x == "y":
df['Employee_Departments__c'] = df['Department'].apply(lambda x: 'Real Estate' if x == 'Operations' else x)
df['Employee_Departments__c'] = df['Department'].apply(lambda x: 'Human Resources' if x == ['C-Suite', 'Human Resources'] else x)
df['GPEC BI'] = df['Employee_Departments__c'].apply(lambda x:'MC' if x == 'Human Resources' or x == 'Real Estate' else '')
df=df.drop(['Department'], axis=1)
else:
df=df.drop(['Department', 'Employee_Departments__c', 'GPEC BI'], axis=1) #Removes the added columns if n is typed.
pass
When I run this code it doesn't label the operations label as Real Estate, instead it leaves it as operations. But when I change C-Suite to label it is Human Resources it works. However, if I switch the Real Estate line and the Human resources line, the Real Estate line works and the HR doesn't.
I'm kinda new to python, but couldn't find how to make this work the way I need it to, when reading Python books and other suggestions.
I tried to run it and expect the column to be filled with the appropriate content that I requested.
Tried doing an or, if, else, and where statement to see if that'll help, but no.
Only one of the lines works and I need both to work.

I think the reason only one of the two lines are working is that you are trying to do an if-elif-else to fill one new column df['Employee_Departments__c']. The second line works because it overrides the first line. I would suggest you change the structure of lambda function following this answer:
https://stackoverflow.com/a/44991451/21088924.
Two lines would then be combined to one line:
df['Employee_Departments__c'] = df['Department'].apply(lambda x: 'Real Estate' if x == 'Operations' else ('Human Resources' if x == ['C-Suite', 'Human Resources'] else x))

Related

Is possible to do nested conditions for a list by comprehension?

I'm challenging myself to turn something like this
if a and b and c:
do_something(x) ## some function
elif a and b and c and d
do_something(x[:-1]) ## the same function but slightly different
to something like this
cosa = [do_something(x) for x in X if a and b and c
or
do_something(x[:-1]) for x in X if a and b and c and d]
Is it possible in Python? I've already been told to use a for loop, but I'm intrigued if there's a way to handle this, given that the function do_something's behaviour only varies by a bit.
A more specific description of what I want to do:
history[chat_name] = [chats.message('chat_type',
line.split(',',4)[3],
line.split(',',4)[1],
line.split(',',4)[2],
line.split(',',4)[4][:-1])
for line
in file
if line.split(',',4)[0] == chat_type
and line.split(',',4)[2] == chat_name]
I'm writing a code that's supposed to emulate a chat app. The variable chat_type indicates if it is a group chat ('grupo') or if it is an individual chat ('regular'). Since, when speaking of a chat group, it doesn't matter who sends the message as long as they are on the group, this code is sufficient and gets the work done.
However, when it comes to an individual chat, the above makes the code include all messages written by anyone to a given recipient. I'd like to add the condition that, if, and only if, the chat_type is set to 'regular', then the code has to make sure the sender is the current user.
I fixed as follows:
if chat_type == 'grupo':
history[chat_name] = [chats.message('chat_type',
line.split(',',4)[3],
line.split(',',4)[1],
line.split(',',4)[2],
line.split(',',4)[4][:-1])
for line
in file
if line.split(',',4)[0] == chat_type
and line.split(',',4)[2] == chat_name]
elif chat_type == 'regular':
history[chat_name] = [chats.message('chat_type',
line.split(',',4)[3],
line.split(',',4)[1],
line.split(',',4)[2],
line.split(',',4)[4][:-1])
for line
in file
if line.split(',',4)[0] == chat_type
and line.split(',',4)[2] == chat_name
and line.split(',',4)[1] == self.username] ##this is the extra condition
I hope this helps in answering my question.
this should be the right way to do what you need
cosa = [do_something(x) if a and b and c else do_something(x[:-1]) if a and b and c and d for x in X]

Reading from a CSV file and using the data to talk to pygame

Having a lot of problems with everything today it seems, first time asking a question and I can't even get my code on here correctly!
Essentially what I'm hoping to do, is to import data from a csv file and use it to select and display images using pygame e.g.
screen.blit(row[0],(0,0))
Where row[0] is Rat1 in the csv file, which has been defined in my code as:
Rat1 = pygame.image.load('Rat1.jpg').convert()
However this throws up "argument 1 must be pygame.Surface, not str", which is fair enough, but I'm really struggling to find a way around this and have found some rather bizarre goings on, bizarre to me at least.
I'm new to this, so the best way I can think to get around this, is to change the row[0] in the csv file to 1, and then to import that to my program and create an integer variable from it, e.g.
x = row[0]
int(x)
if x == 1:
x = Rat1
and then plug x in to pygame, e.g.
screen.blit(x,(0,0))
This works if I just have x = Rat1 as a global variable, however doing it as above doesn't change x to = 1, it stays as row[x] so it just doesn't like it.
It boils down to this happening when I tried to test it a bit...
import csv
out = open("CSVTest.csv","rb")
data = csv.reader(out)
data = [row for row in data]
out.close()
print row[0] #this causes it to print a 1, so I know
#it's working and reading as it should
x = row[0] #make a variable
int(x) #doesn't throw up an error, so I assume it
#has changed the csv string to an integer
print x #prints a 1 again
if x == 1:
print "hello?" #doesn't print, so clearly doesn't
#recognise x as an integer
if x == 49: #I'm getting desperate now, ASCII 1?!
print "hello?!" #No joy
So what on earth is it, it doesn't seem to be your standard string, as won't convert obviously in to an integer.
I've tried pygame.image.fromstring(), where the answer probably lies, but I can't get it to work.
Can anyone point out what is wrong with it all and how I can easily call data from a csv file and at least get it recognised as an integer or even better, inserted in to a bit of pygame code and displayed?
I've read things from csv files and displayed images with pygame without a hitch, but getting the two to mate seems tough, beyond me certainly.
Any help is much appreciated!
int() is the Python standard built-in function to convert a string into an integer value. You call it with a string containing a number as the argument, and it returns the number converted to an actual integer:
print int("1") + 1
The above prints 2.
If you know the structure of your list (that it simply contains lists, only one level), you could do this:
T2 = [map(int, x) for x in T1]
Or...
Try this.
x = "1"
x is a string because it has quotes around it, but it has a number in it.
x = int(x)
Since x has the number 1 in it, I can turn it in to a integer.
To see if a string is a number, you can do this.
def is_number(var):
try:
if var == int(var):
return True
except Exception:
return False
x = "1"
y = "test"
x_test = is_number(x)
print(x_test)
It should print to IDLE True because x is a number.
y_test = is_number(y)
print(y_test)
It should print to IDLE False because y in not a number.

Removing rows dependent on one column Python

I'm working on taking apart a python script piece by piece to get a better understanding of 1.) how python works & 2.) what this particular script does & if I can make it better (i.e. usable by slightly more varied inputs).
Okay so, there is a line in my code that looks like this:
thisChrominfo = chrominfo[thisChrom]
Where chrominfo calls a dictionary set that looks like this:
{'chrY': ['chrY', '59373566', '3036303846'], 'chrX': ['chrX', '155270560', '2881033286'], 'chr13': ['chr13', '115169878', '2084766301'], 'chr12': ['chr12', '133851895', '1950914406'], 'chr11': ['chr11', '135006516', '1815907890'], 'chr10': ['chr10', '135534747', '1680373143'], 'chr17': ['chr17', '81195210', '2500171864'], 'chr16': ['chr16', '90354753', '2409817111'], 'chr15': ['chr15', '102531392', '2307285719'], 'chr14': ['chr14', '107349540', '2199936179'], 'chr19': ['chr19', '59128983', '2659444322'], 'chr18': ['chr18', '78077248', '2581367074'], 'chrM': ['chrM', '16571', '3095677412'], 'chr22': ['chr22', '51304566', '2829728720'], 'chr20': ['chr20', '63025520', '2718573305'], 'chr21': ['chr21', '48129895', '2781598825'], 'chr7': ['chr7', '159138663', '1233657027'], 'chr6': ['chr6', '171115067', '1062541960'], 'chr5': ['chr5', '180915260', '881626700'], 'chr4': ['chr4', '191154276', '690472424'], 'chr3': ['chr3', '198022430', '492449994'], 'chr2': ['chr2', '243199373', '249250621'], 'chr1': ['chr1', '249250621', '0'], 'chr9': ['chr9', '141213431', '1539159712'], 'chr8': ['chr8', '146364022', '1392795690']}
and thisChrom calls a single column (non-integer) that includes things like this:
'*' to `chr4`to `chrY` etc.
thisChrom only returns one value at a time, because it relies on a piece higher up in the file that specifies only a single row:
for x in INFILE:
arow = x.rstrip().split("\t")
thisChrom = arow[2]
thisChrompos = arow[3]
So it's pulling one column from one row.
The whole thing falls apart when values like '*' are present in arow, because that's not in the chrominfo dictionary. At first I thought I should just go ahead and add it to the dictionary, but now I'm thinking it would be easier and better to instead add a line at the top that says something like, if arow[2] == '*' then delete it, else continue.
I know it should look something like this:
for x in INFILE:
arow = x.rstrip().split("\t")
thisChrom = arow[2]
thisChrompos = arow[3]
if arow == '*': arow.remove(*)
else:
continue
but I haven't been able to get the syntax quite right. All of my Python is self & stackoverflow taught, so I appreciate your suggestions and guidance. Sorry if that was an over-explanation of something that is very simple for most experts (I am not an expert).
The continue keyword is somewhat non-obvious. What it does is skip the remaining contents of the loop, and start the next iteration. So, what you wrote will skip the rest of the loop only if arow is not equal to '*'.
Instead of
if arow == '*': arow.remove(*)
else:
continue
# process the row
you might simply want to either use a simple if condition:
if arow != '*':
# process the row
or use continue in the way you probably intended:
if arow == '*': continue
# process the row
See how it works in the opposite way of what you thought? Also, you don't need an else in this case because of how the continue skips the rest of the loop.
If you're familiar with the break keyword, it may make more sense as a comparison. The break keyword stops the loop entirely - it "breaks" out of it and moves on. The continue keyword is simply a "weaker" version of that - it "breaks" out of the current iteration but not all the way out of the loop.

Why re is not compiling 'if' when there is 'else'?

Hello I'm facing a problem and I don't how to fix it. All I know is that when I add an else statement to my if statement the python execution always goes to the else statement even there is there a true statement in if and can enter the if statement.
Here is the script, without the else statement:
import re
f = open('C:\Users\Ziad\Desktop\Combination\MikrofullCombMaj.txt', 'r')
d = open('C:\Users\Ziad\Desktop\Combination\WhatsappResult.txt', 'r')
w = open('C:\Users\Ziad\Desktop\Combination\combination.txt','w')
s=""
av =0
b=""
filtred=[]
Mlines=f.readlines()
Wlines=d.readlines()
for line in Wlines:
Wspl=line.split()
for line2 in Mlines:
Mspl=line2.replace('\n','').split("\t")
if ((Mspl[0]).lower()==(Wspl[0])):
Wspl.append(Mspl[1])
if(len(Mspl)>=3):
Wspl.append(Mspl[2])
s="\t".join(Wspl)+"\n"
if s not in filtred:
filtred.append(s)
break
for x in filtred:
w.write(x)
f.close()
d.close()
w.close()
with the else statement and I want else for the if ((Mspl[0]).lower()==(Wspl[0])):
import re
f = open('C:\Users\Ziad\Desktop\Combination\MikrofullCombMaj.txt', 'r')
d = open('C:\Users\Ziad\Desktop\Combination\WhatsappResult.txt', 'r')
w = open('C:\Users\Ziad\Desktop\Combination\combination.txt','w')
s=""
av =0
b=""
filtred=[]
Mlines=f.readlines()
Wlines=d.readlines()
for line in Wlines:
Wspl=line.split()
for line2 in Mlines:
Mspl=line2.replace('\n','').split("\t")
if ((Mspl[0]).lower()==(Wspl[0])):
Wspl.append(Mspl[1])
if(len(Mspl)>=3):
Wspl.append(Mspl[2])
s="\t".join(Wspl)+"\n"
if s not in filtred:
filtred.append(s)
break
else:
b="\t".join(Wspl)+"\n"
if b not in filtred:
filtred.append(b)
break
for x in filtred:
w.write(x)
f.close()
d.close()
w.close()
first of all, you're not using "re" at all in your code besides importing it (maybe in some later part?) so the title is a bit misleading.
secondly, you are doing a lot of work for what is basically a filtering operation on two files. Remember, simple is better than complex, so for starters, you want to clean your code a bit:
you should use a little more indicative names than 'd' or 'w'. This goes for 'Wsplt', 's' and 'av' as well. Those names don't mean anything and are hard to understand (why is the d.readlines named Wlines when ther's another file named 'w'? It's really confusing).
If you choose to use single letters, it should still make sense (if you iterate over a list named 'results' it makes sense to use 'r'. 'line1' and 'line2' however, are not recommanded for anything)
You don't need parenthesis for conditions
You want to use as little variables as you can as to not get confused. There's too much different variables in your code, it's easy to get lost. You don't even use some of them.
you want to use strip rather than replace, and you want the whole 'cleaning' process to come first and then just have a code the deals with the filtering logic on the two lists. If you split each line according to some logic, and you don't use the original line anywhere in the iteration, then you can do the whole thing in the beggining.
Now, I'm really confused what you're trying to achieve here, and while I don't understand why your doing it that way, I can say that looking at your logic you are repeating yourself a lot. The action of checking against the filtered list should only happend once, and since it happens regardless of whether the 'if' checks out or not, I see absolutely no reason to use an 'else' clause at all.
Cleaning up like I mentioned, and re-building the logic, the script looks something like this:
# PART I - read and analyze the lines
Wappresults = open('C:\Users\Ziad\Desktop\Combination\WhatsappResult.txt', 'r')
Mikrofull = open('C:\Users\Ziad\Desktop\Combination\MikrofullCombMaj.txt', 'r')
Wapp = map(lambda x: x.strip().split(), Wappresults.readlines())
Mikro = map(lambda x: x.strip().split('\t'), Mikrofull.readlines())
Wappresults.close()
Mikrofull.close()
# PART II - filter using some logic
filtred = []
for w in Wapp:
res = w[:] # So as to copy the list instead of point to it
for m in Mikro:
if m[0].lower() == w[0]:
res.append(m[1])
if len(m) >= 3 :
res.append(m[2])
string = '\t'.join(res)+'\n' # this happens regardles of whether the 'if' statement changed 'res' or not
if string not in filtred:
filtred.append(string)
# PART III - write the filtered results into a file
combination = open('C:\Users\Ziad\Desktop\Combination\combination.txt','w')
for comb in filtred:
combination.write(comb)
combination.close()
I can't promise it will work (because again, like I said, I don't know what you're trying to achive) but this should be a lot easier to work with.

Serial Key Generation and Validation

I'm toying around with writing creating a serial code generator/validator, but I can't seem to get how to do a proper check.
Here's my generator code:
# Serial generator
# Create sequences from which random.choice can choose
Sequence_A = 'ABCDEF'
Sequence_B = 'UVWQYZ'
Sequence_C = 'NOPQRS'
Sequence_D = 'MARTIN'
import random
# Generate a series of random numbers and Letters to later concatenate into a pass code
First = str(random.randint(1,5))
Second = str(random.choice(Sequence_A))
Third = str(random.randint(6,9))
Fourth = str(random.choice(Sequence_B))
Fifth = str(random.randint(0,2))
Sixth = str(random.choice(Sequence_C))
Seventh = str(random.randint(7,8))
Eighth = str(random.choice(Sequence_D))
Ninth = str(random.randint(3,5))
serial = First+Second+Third+Fourth+Fifth+Sixth+Seventh+Eighth+Ninth
print serial
I'd like to make a universal check so that my validation code will accept any key generated by this.
My intuition was to create checks like this:
serial_check = raw_input("Please enter your serial code: ")
# create a control object for while loop
control = True
# Break up user input into list that can be analyzed individually
serial_list = list(serial_check)
while control:
if serial_list[0] == range(1,5):
pass
elif serial_list[0] != range(1,5):
control = False
if serial_list[1] == random.choice('ABCDEF'):
pass
elif serial_list[1] != random.choice('ABCDEF'):
control = False
# and so on until the final, where, if valid, I would print that the key is valid.
if control == False:
print "Invalid Serial Code"
I'm well aware that the second type of check won't work at all, but it's a place holder because I've got no idea how to check that.
But I thought the method for checking numbers would work, but it doesn't either.
The expression `range(1, 5)' creates a list of numbers from 1 to 4. So in your first test, you're asking whether the first character in your serial number is equal to that list:
"1" == [1, 2, 3, 4]
Probably not...
What you probably want to know is whether a digit is in the range (i.e. from 1 to 5, I assume, not 1 to 4).
Your other hurdle is that the first character of the serial is a string, not an integer, so you would want to take the int() of the first character. But that will raise an exception if it's not a digit. So you must first test to make sure it's a digit:
if serial_list[0].isdigit() and int(serial_list[0]) in range(1, 6):
Don't worry, if it's not a digit, Python won't even try to evaluate the part after and. This is called short-circuiting.
However, I would not recommend doing it this way. Instead, simply check to make sure it is at least "1" and no more than "5", like this:
if "1" <= serial_list <= "5":
You can do the same thing with each of your tests, varying only what you're checking.
Also, you don't need to convert the serial number to a list. serial_check is a string and accessing strings by index is perfectly acceptable.
And finally, there's this pattern going on in your code:
if thing == other:
pass
elif thing != other:
(do something)
First, because the conditions you are testing are logical opposites, you don't need elif thing != other -- you can just say else, which means "whatever wasn't matched by any if condition."
if thing == other:
pass
else:
(do something)
But if you're just going to pass when the condition is met, why not just test the opposite condition to begin with? You clearly know how to write it 'cause you were putting it in the elif. Put it right in the if instead!
if thing != other:
(do something)
Yes, each of your if statements can easily be cut in half. In the example I gave you for checking the character range, probably the easiest way to do it is using not:
if not ("1" <= serial_list <= "5"):
Regarding your python, I'm guessing that when your wrote this:
if serial_list[0] == range(1,5):
You probably meant this:
if 1 <= serial_list[0] <= 5:
And when you wrote this:
if serial_list[1] == random.choice('ABCDEF'):
You probably meant this:
if serial_list[1] in 'ABCDEF':
There are various other problems with your code, but I'm sure you'll improve it as you learn python.
At a higher level, you seem to be trying to build something like a software activation code generator/validator. You should know that just generating a string of pseudo-random characters and later checking that each is in range is an extremely weak form of validation. If you want to prevent forgeries, I would suggest learning about HMAC (if you're validating on a secure server) or public key cryptography (if you're validating on a user's computer) and incorporating that into your design. There are libraries available for python that can handle either approach.

Categories

Resources