In Python, I would like to create a new variable c
based on the value of a
and b
.
if a in ('GBP', 'AUD', 'CNY', 'NZD'):
if b == '[00Y, 01Y]':
c= '90'
elif b == '[01Y, 02Y]':
c = '85'
elif b == '[02Y, 03Y]':
c = '80'
elif b == '[03Y, 04Y]':
c = '75'
elif b == '[04Y, 05Y]':
c = '70'
elif a in ('EUR', 'USD', 'CHF', 'CAD', 'SGD', 'HKD', 'JPY'):
if b == '[00Y, 01Y]':
c = '95'
elif b == '[01Y, 02Y]':
c = '90'
elif b == '[02Y, 03Y]':
c = '85'
elif b == '[03Y, 04Y]':
c = '80'
elif b == '[04Y, 05Y]':
c = '75'
elif b == '[05Y, 07Y]':
c = '60'
elif b == '[07Y, 10Y]':
c = '55'
a
and b
are columns of a dataframe and I have to use apply
to finally obtain what I desire.
Although this perfectly works, I think it is long code for such a small operation and I wonder if there is a more elegant way to do the same. I know the np.select
condition but it forces me to repeat the condition on `a, which I find is not elegant either.
Thanks,
My initial question is maybe not clear enough. I want to compact the following code without having to repeat all conditions:
def f1(a, b, c, d):
if a == 1 and b <= 5 and c in ('abc', 'def') and d: s = 75
if a == 1 and b <= 5 and c in ('abc', 'def') and not d: s = 83
if a == 1 and b <= 5 and c == 'xyz' and d: s = 77
if a == 1 and b <= 5 and c == 'xyz' and not d: s = 17
if a == 1 and 5 < b <= 8 and c in ('abc', 'def') and d: s = 28
if a == 1 and 5 < b <= 8 and c in ('abc', 'def') and not d: s = 39
if a == 1 and 5 < b <= 8 and c == 'xyz' and d: s = 10
if a == 1 and 5 < b <= 8 and c == 'xyz' and not d: s = 45
if a == 1 and b > 8 and c in ('abc', 'def') and d: s = 59
if a == 1 and b > 8 and c in ('abc', 'def') and not d: s = 48
if a == 1 and b > 8 and c == 'xyz' and d: s = 29
if a == 1 and b > 8 and c == 'xyz' and not d: s = 24
if a == 2 and b <= 5 and c in ('abc', 'def') and d: s = 39
if a == 2 and b <= 5 and c in ('abc', 'def') and not d: s = 51
if a == 2 and b <= 5 and c == 'xyz' and d: s = 69
if a == 2 and b <= 5 and c == 'xyz' and not d: s = 42
if a == 2 and 5 < b <= 8 and c in ('abc', 'def') and d: s = 23
if a == 2 and 5 < b <= 8 and c in ('abc', 'def') and not d: s = 11
if a == 2 and 5 < b <= 8 and c == 'xyz' and d: s = 12
if a == 2 and 5 < b <= 8 and c == 'xyz' and not d: s = 89
if a == 2 and b > 8 and c in ('abc', 'def') and d: s = 54
if a == 2 and b > 8 and c in ('abc', 'def') and not d: s = 23
if a == 2 and b > 8 and c == 'xyz' and d: s = 22
if a == 2 and b > 8 and c == 'xyz' and not d: s = 98
if a == 3 and b <= 5 and c in ('abc', 'def') and d: s = 91
if a == 3 and b <= 5 and c in ('abc', 'def') and not d: s = 15
if a == 3 and b <= 5 and c == 'xyz' and d: s = 55
if a == 3 and b <= 5 and c == 'xyz' and not d: s = 36
if a == 3 and 5 < b <= 8 and c in ('abc', 'def') and d: s = 66
if a == 3 and 5 < b <= 8 and c in ('abc', 'def') and not d: s = 82
if a == 3 and 5 < b <= 8 and c == 'xyz' and d: s = 20
if a == 3 and 5 < b <= 8 and c == 'xyz' and not d: s = 98
if a == 3 and b > 8 and c in ('abc', 'def') and d: s = 77
if a == 3 and b > 8 and c in ('abc', 'def') and not d: s = 23
if a == 3 and b > 8 and c == 'xyz' and d: s = 41
if a == 3 and b > 8 and c == 'xyz' and not d: s = 84
return s
I found this solution which uses itertools.product
. but we need to pay attention to the order of listvalues
:
import numpy as np
import itertools
def f(a, b, c, d):
listconditions = [[a==1, a==2, a==3],
[b <= 5, 5 < b <= 8, b > 8],
[c in ("abc", "def"), c == 'xyz'],
[d, not d]]
listvalues = [75, 83, 77, 17, 28, 39, 10, 45, 59, 48, 29, 24,
39, 51, 69, 42, 23, 11, 12, 89, 54, 23, 22, 98,
91, 15, 55, 36, 66, 82, 20, 98, 77, 23, 41, 84]
allcombinations = itertools.product(*listconditions)
test = [np.logical_and.reduce(i) for i in allcombinations]
return sum(np.array(test) * listvalues)
f(1,7,'abc',False)
39
You could use a dictionary to contain indices for a
and values in b
:
options_a = {'GBP': 0, 'AUD': 0, 'CNY': 0, 'NZD': 0, 'EUR': 1, 'USD': 1, 'CHF': 1, 'CAD': 1, 'SGD': 1, 'HKD': 1, 'JPY': 1}
options_b = {'[00Y, 01Y]': ('90', '95'), '[01Y, 02Y]': ('85', '90'), '[02Y, 03Y]': ('80', '85'), '[03Y, 04Y]': ('75', '80'), '[04Y, 05Y]': ('70', '75'), '[05Y, 07Y]': (None, '60'), '[07Y, 10Y]': (None, '55')}
# Get the index of the tuple by looking up 'a' first
idx = options_a[a]
# Then use that index when you look up 'b' to grab the correct value for 'c'
c = options_b[b][idx]
If you get any combinations you didn't plan for, it will raise a KeyError
, which you may or may not want to handle:
try:
idx = options_a[a]
tup = options_b[b]
except KeyError:
print("Do something")
else:
c = tup[idx]
Use for loop and list to do what you want I assume that, you need to decrease the value by 5
tupel1 = ('GBP', 'AUD', 'CNY', 'NZD')
tuple2 = ('EUR', 'USD', 'CHF', 'CAD', 'SGD', 'HKD', 'JPY')
listb = ['[00Y, 01Y]' ,'[02Y, 03Y]','[03Y, 04Y]','[04Y, 05Y]',]
for i in range(listb):
if listb[i]==b:
if a in tuble1:
c = str(90 - 5*i)
elif a in tuble2:
c = str(95 -5*i)
Another take, a one-liner:
(95 if a in {'EUR', 'USD', 'CHF', 'CAD', 'SGD', 'HKD', 'JPY'} else 90) - 5 * [0, 1, 2, 3, 4, 5, 7].index(int(b[1:3]))
Or packing it more, but getting dirty:
(95 if a in 'EUR USD CHF CAD SGD HKD JPY' else 90) - 5 * [0, 1, 2, 3, 4, 5, 7].index(int(b[1:3]))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.