Empty a variable without destroying it - python

I have this piece of code:
a = "aa"
b = 1
c = { "b":2 }
d = [3,"c"]
e = (4,5)
letters = [a, b, c, d, e]
And I want to do something with it, which will empty them. Without losing their type.
Something like this:
>>EmptyVars(letters)
['',0,{},[],()]
Any hint?

Do this:
def EmptyVar(lst):
return [type(i)() for i in lst]
type() produces the type object for each value, which when called produces an 'empty' new value.
Demo:
>>> a = "aa"
>>> b = 1
>>> c = { "b":2 }
>>> d = [3,"c"]
>>> e = (4,5)
>>> letters = [a, b, c, d, e]
>>> def EmptyVar(lst):
... return [type(i)() for i in lst]
...
>>> EmptyVar(letters)
['', 0, {}, [], ()]

Similar way, just type(i)() replaced by i.__class__():
a = "aa"
b = 1
c = {"b": 2}
d = [3, "c"]
e = (4, 5)
letters = [a, b, c, d, e]
def empty_var(lst):
return [i.__class__() for i in lst]
print(empty_var(letters))
['', 0, {}, [], ()]

We can do this with the help of type() function which is generally used to display the type of any object or variable in python.
Here is the solution :
a = "aa"
b = 1
c = {"b" : 2}
d = [3, "c"]
e = (4,5)
letters = [a,b,c,d,e]
print([type(i)() for i in letters])

Related

Compare 2 list columns in pandas and find the diff

DataFrame
df = pd.DataFrame({
'Id': [1,1,1,1,2,2,3,4,4,4],
'Col_1':['AD11','BZ23','CQ45','DL36','LM34','MM23','DL35','AD11','BP23','CQ45'],
'Col_2':['AD11',nan,nan,'DL36',nan,nan,'DL35',nan,nan,'CQ45']]
}, columns=['Id','Col_1','Col_2'])
Looks Like
Original data frame looks like this
Please note that Col_1 & Col_2 has alpha numeric values and has more than one character. For eg : 'AD34' , 'EC45', etc.
After groupby and reset index
g = df.groupby('Id')['Col_1','Col_2'].agg(['unique'])
g= g.reset_index(drop=True)
g.columns = [''.join(col).strip() for col in g.columns.values]
I want to
store results that match in Match column
results that do not match No_match column
Result :
I tried to use some logic from this
post but doesnt solve my issue.
Is there a better way to do the transformation for my requirement ?
Appreciate the help.
First remove missing values from list and then use set.intersection and set.difference:
g = df.groupby('Id')[['Col_1','Col_2']].agg([lambda x: x.dropna().unique().tolist()])
g= g.reset_index(drop=True)
g.columns = [f'{a}_unique' for a, b in g.columns]
z = list(zip(g['Col_1_unique'], g['Col_2_unique']))
g['Match'] = [list(set(a).intersection(b)) for a, b in z]
g['No_Match'] = [list(set(a).difference(b)) for a, b in z]
print (g)
Col_1_unique Col_2_unique Match No_Match
0 [AD11, BZ23, CQ45, DL36] [AD11, DL36] [DL36, AD11] [CQ45, BZ23]
1 [LM34, MM23] [] [] [LM34, MM23]
2 [DL35] [DL35] [DL35] []
3 [AD11, BP23, CQ45] [CQ45] [CQ45] [AD11, BP23]
Here, my simple logic is to compare both list, by same value on same positions.
Such as, [a,b,c] & [b,a,c] so match will be [c] only.
Code:
df = pd.DataFrame({
'Id': [1,1,1,1,2,2,3,4,4,4],
'Col_1':['A','B','C','D','L','M','D','A','B','C'],
'Col_2':['A','','','D','','','D','', '', 'C']
}, columns=['Id','Col_1','Col_2'])
#In order to compare list by values and position I needed to add unique value on null value
#So the both list length would be same
df['Col_2'] = df.apply(lambda x : x.name if x.Col_2=='' else x.Col_2, axis=1)
g = df.groupby('Id')['Col_1','Col_2'].agg(['unique'])
g= g.reset_index(drop=True)
g.columns = [''.join(col).strip() for col in g.columns.values]
g['Match'] = g.apply(lambda x: [a for a, b in zip(x.Col_1unique, x.Col_2unique) if a==b], axis=1)
g['Not_Match'] = g.apply(lambda x: [a for a, b in zip(x.Col_1unique, x.Col_2unique) if a!=b], axis=1)
g
Output:
Col_1unique Col_2unique Match Not_Match
0 [A, B, C, D] [A, 1, 2, D] [A, D] [B, C]
1 [L, M] [4, 5] [] [L, M]
2 [D] [D] [D] []
3 [A, B, C] [7, 8, C] [C] [A, B]
Please try to use the below code but make it more efficient, for time being i tried the below,
import pandas as pd
df = pd.DataFrame({
'Id': [1, 1, 1, 1, 2, 2, 3, 4, 4, 4],
'Col_1': ['A', 'B', 'C', 'D', 'L', 'M', 'D', 'A', 'B', 'C'],
'Col_2': ['A', 'nan', 'nan', 'D', 'nan', 'nan', 'D', 'nan', 'nan', 'C']})
print(df)
df['Match'] = ''
df['No-Match'] = ''
for i, row in df.iterrows():
if row['Col_1'] == row['Col_2']:
df.at[i, 'Match'] = row['Col_1']
else:
df.at[i, 'No-Match'] = row['Col_1']
print(df)
g = df.groupby('Id')['Id','Col_1','Col_2','Match','No-Match'].agg(['unique'])
g= g.reset_index(drop=True)
g.columns = [''.join(col).strip() for col in g.columns.values]
print(g)
Once you run this, you will get the below output:
Idunique Col_1unique Col_2unique Matchunique No-Matchunique
0 [1] [A, B, C, D] [A, nan, D] [A, D] [B, C]
1 [2] [L, M] [nan] [] [L, M]
2 [3] [D] [D] [D] []
3 [4] [A, B, C] [nan, C] [C] [A, B]

I have three arrays of different sizes that I'm trying to print into a table

a = [1, 2, 3]
b = [a, b, c, d]
c = ["why", "cant", "i", "make", "this", "work"]
Desired output:
a b c
1 a why
2 b cant
3 c I
d make
this
work
you can reference this code.
a = [1, 2, 3]
b = ['a', 'b', 'c', 'd']
c = ["why", "cant", "i", "make", "this", "work"]
def get_safenode(l, i):
if i<len(l):
an=l[i]
else:
an=''
return str(an)
maxlen = max(len(a), len(b), len(c))
print('%3s %3s %-5s' % ('a','b','c'))
for i in range(maxlen):
an = get_safenode(a, i)
bn = get_safenode(b, i)
cn = get_safenode(c, i)
print('%3s %3s %-5s'%(an, bn, cn))
The output is this.
a b c
1 a why
2 b cant
3 c i
d make
this
work

Why is the index only changing when I use different values?

I just started programming in Python, and I can't figure out how to make the index change if I want the values in the list to be the same. What I want is for the index to change, so it will print 0, 1, 2, but all I get is 0, 0, 0. I tried to change the values of the list so that they were different, and then I got the output I wanted. But I don't understand why it matters what kind of values I use, why would the index care about what is in the list?
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
justTesting = [[a, b], [c, d], [e, f]]
for item in justTesting:
something = justTesting.index(item)
print (something)
I'm using python 3.6.1 if that mattters
Because each list (designated 'item' in your loop) is [0, 0] this means the line:
something = justTesting.index(item)
will look for the first instance of the list [0, 0] in the list for each 'item' during the iteration. As every item in the list is [0, 0] the first instance is at position 0.
I have prepared an alternative example to illustrate the point
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
justTesting = [[a, b], [c, d], [e, f]]
for item in justTesting:
print(item)
something = justTesting.index(item)
print(something)
This results in the following:
[1, 2]
0
[3, 4]
1
[5, 6]
2
It's because your list only contains [0, 0]!
So basically, if we replace all the variables with their values, we get:
justTesting = [[0, 0], [0, 0], [0, 0]]
And using .index(item) will return the first occurrence of item if any. Since item is always [0, 0] and it first appears at justTesting[0], you will always get 0! Try changing up the values in each list and try again. For example, this works:
b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for item in b:
print(b.index(item))
Which returns:
0, 1, 2, 3, 4, 5, 6, 7, 8
if the results were on a single line.
Try it here!
Read the documentation: the default for index is to identify the first occurence. You need to use the start parameter as well, updating as you go: search only the list after the most recent find.
something = justTesting.index(item, something+1)
That's because you are iterating over a list of lists.
Every item is actually a list, and you are executing list.index() method which returns the index of the element in the list.
This is a little tricky. Since you actually have 3 lists, of [0, 0] their values will be the same when testing for equality:
>>> a = 0
>>> b = 0
>>> c = 0
>>> d = 0
>>> ab = [a, b]
>>> cd = [c, d]
>>>
>>> ab is cd
False
>>> ab == cd
True
>>>
Now when you run list.index(obj) you are looking for the 1st index that matches the object. Your code actually runs list.index([0, 0]) 3 times and returns the first match, which is at index 0.
Put different values inside a, b, c lists and it would work as you expect.
Your code:
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
justTesting = [[a, b], [c, d], [e, f]]
for item in justTesting:
something = justTesting.index(item)
print (something)
is equivalent to:
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
ab = [a, b]
cd = [c, d]
ef = [e, f]
justTesting = [ab, cd, ef]
# Note that ab == cd is True and cd == ef is True
# so all elements of justTesting are identical.
#
# for item in justTesting:
# something = justTesting.index(item)
# print (something)
#
# is essentially equivalent to:
item = justTesting[0] # = ab = [0, 0]
something = justTesting.index(item) # = 0 First occurrence of [0, 0] in justTesting
# is **always** at index 0
item = justTesting[1] # = cd = [0, 0]
something = justTesting.index(item) # = 0
item = justTesting[2] # = ef = [0, 0]
something = justTesting.index(item) # = 0
justTesting does not change as you iterate and the first position in justTesting at which [0,0] is found is always 0.
But I don't understand why it matters what kind of values I use, why would the index care about what is in the list?
Possibly what is confusing you is the fact that index() does not search for occurrences of the item "in abstract" but it looks at the values of items in a list and compares those values with a given value of item. That is,
[ab, cd, ef].index(cd)
is equivalent to
[[0,0],[0,0],[0,0].index([0,0])
and the first occurrence of [0,0] value (!!!) is at 0 index of the list for your specific values for a, b, c, d, e, and f.

Python find index of all array elements in another array

I am trying to do the following:
import numpy as np
A = np.array([1,5,2,7,1])
B = np.sort(A)
print B
>>> [1,1,2,5,7]
I want to find the location of all elements in B as in original array A. i.e. I want to create an array C such that
print C
>>[0,4,2,1,3]
which refers to 1 in B being present in A at 0 and 4th location, 5 in B was present in A at 1st location, etc.
I tried using np.where( B == A) but it produces gibberish
import numpy as np
A = np.array([1,5,2,7,1])
print np.argsort(A) #prints [0 4 2 1 3]
If you don't want to imporr numpy for any reason you can also use this code:
a = [1,5,2,7,1]
b = zip(a, range(len(a)))
tmp = sorted(b, key=lambda x: x[0])
c = map( lambda x: x[1], tmp)
print c
[0, 4, 2, 1, 3]
https://repl.it/CVbI
A = [1,5,2,7,1]
for i,e in sorted(enumerate(A), key=lambda x: x[1]):
print(i, e)
B = [x for x,_ in sorted(enumerate(A), key=lambda x: x[1])]
A = sorted(A)
print(A)
print(B)

How to print list items in python

I have written the following code:
def count():
a = 1
b = 5
c = 2
d = 8
i = 0
list1 = [a, b, c, d]
le = len(list1)
while (i < le):
x = max(list1)
print(x)
list1.remove(x)
i = i + 1
What I want to do is to print the largest number with its variable name like:
d:8
b:5
c:2
but using the above code I can only print the ascending list of numbers, not the corresponding variable names. Please suggest a way to fix this.
Use a dict instead:
In [2]: dic=dict(a=1, b=5, c=2, d=8)
In [3]: dic
Out[3]: {'a': 1, 'b': 5, 'c': 2, 'd': 8}
In [5]: sortedKeys=sorted(dic, key=dic.get, reverse=True)
In [6]: sortedKeys
Out[6]: ['d', 'b', 'c', 'a']
In [7]: for i in sortedKeys:
...: print i, dic[i]
...:
d 8
b 5
c 2
a 1
I think you can use OrderedDict()
from collections import OrderedDict
a, b, c, d = 1, 2, 3, 6
vars = {
'a' : a,
'b' : b,
'c' : c,
'd' : d
}
d_sorted_by_value = OrderedDict(sorted(vars.items(), key=x.get, reverse=True))
for k, v in d_sorted_by_value.items():
print "{}: {}".format(k,v)
List don't save variable names

Categories

Resources