I have a 2-D List as follows:
[
[6 4 4 2 5 5 4 5 4 1 3 5]
[4 3 6 5 4 4 5 1 5 5 2 4]
[2 5 2 0 4 5 4 4 2 3 2 6]
[5 5 4 3 5 4 6 7 3 4 4 4]
[3 5 6 5 6 5 3 5 3 4 7 4]
[4 5 5 4 5 4 7 5 3 5 4 1]
[2 5 3 3 5 3 4 4 3 3 1 3]
[2 5 5 2 5 4 6 2 5 6 2 5]
]
Conditions:
compare column 1,5 and 9 (in steps of 4) - row-wise and process them in the following order
If one of them is zero - do nothing. Go to Step 2
(6,5,4) - none of them zero so go to step 2
If they are all equal - change all of them to zero. If not go Step 3
Take the lowest of the three and subtract each by this minimum
Repeat this with next three elements (2,6,10) until (4,8,12)
How to do efficiently this in python using pandas or numpy or even list operation.
Any help appreciated. Thanks!
You could write a custom function and then apply that functions to every element in the array.
def check_conditions(x):
for i in range(4):
if x[i] == 0 or x[i+4] == 0 or x[i+8] == 0:
continue
elif x[i] == x[i+4] == x[i+8]:
x[i] = 0
x[i+4] = 0
x[i+8] = 0
else:
min_val = min(x[i], x[i+4], x[i+8])
x[i] -= min_val
x[i+4] -= min_val
x[i+8] -= min_val
return x
new_arr = [check_conditions(x) for x in arr]
To get the following result.
print(new_arr)
[[2, 3, 1, 2, 1, 4, 1, 5, 0, 0, 0, 5],
[0, 0, 4, 5, 0, 1, 3, 1, 1, 2, 0, 4],
[0, 2, 0, 0, 2, 2, 2, 4, 0, 0, 0, 6],
[2, 1, 0, 3, 2, 0, 2, 7, 0, 0, 0, 4],
[0, 1, 3, 5, 3, 1, 0, 5, 0, 0, 4, 4],
[1, 1, 1, 4, 2, 0, 3, 5, 0, 1, 0, 1],
[0, 2, 2, 3, 3, 0, 3, 4, 1, 0, 0, 3],
[0, 1, 3, 2, 3, 0, 4, 2, 3, 2, 0, 5]]
I am trying to change this list
['AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5',
'BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2',
'K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1']
to something that looks like this
AAAAA -- [4, 2, 1, 2, 4, 2, 4, 4, 5, 2, 2, 1, 5, 2, 4, 3, 1, 1, 3, 3, 5]
BBB -- [5, 2, 1, 2, 4, 5, 4, 4, 1, 2, 2, 2, 4, 4, 4, 3, 1, 2, 3, 3, 2]
K -- [4, 1, 2, 1, 2, 1, 2, 5, 1, 1, 1, 1, 4, 2, 2, 1, 5, 1, 3, 4, 1]
i have tried multiple ways and cant figure it out
You just need to split the elements in each string, take the first element and set it as key of the dictionary, and convert the rest of the elements to integers, and store as values:
list_ = ['AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5',
'BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2',
'K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1']
dict_ = {}
for string in list_:
alpha, *numbers = string.split()
dict_[alpha] = [*map(int,numbers)]
for alpha, numbers in dict_.items():
print(f"{alpha} -- {numbers}")
Output:
AAAAA -- [4, 2, 1, 2, 4, 2, 4, 4, 5, 2, 2, 1, 5, 2, 4, 3, 1, 1, 3, 3, 5]
BBB -- [5, 2, 1, 2, 4, 5, 4, 4, 1, 2, 2, 2, 4, 4, 4, 3, 1, 2, 3, 3, 2]
K -- [4, 1, 2, 1, 2, 1, 2, 5, 1, 1, 1, 1, 4, 2, 2, 1, 5, 1, 3, 4, 1]
If you want to go fancy:
generator_ = (f"{alpha} -- {[*map(int,numbers)]}" for alpha, *numbers in [l.split() for l in list_])
print(*generator_, sep = '\n')
If you want to reproduce what you asked in the question:
x = ['AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5', 'BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2', 'K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1']
for elem in x:
split = elem.split(" ")
print("{} -- {}".format(split[0],[int(i) for i in split[1:]]))
This:
Loops through the list x
Splits its items into a separate list split
Separates first element from rest with a "--" when printing
Or using a dictionary:
x = ['AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5', 'BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2', 'K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1']
# Create dictionary following above logic
d = dict()
for elem in x:
split = elem.split(" ")
d.update({split[0] : [int(i) for i in split[1:]]})
# Loop through its keys and values and print as needed
for k, v in d.items():
print("{} -- {}".format(k, v))
Output:
K -- [4, 1, 2, 1, 2, 1, 2, 5, 1, 1, 1, 1, 4, 2, 2, 1, 5, 1, 3, 4, 1]
AAAAA -- [4, 2, 1, 2, 4, 2, 4, 4, 5, 2, 2, 1, 5, 2, 4, 3, 1, 1, 3, 3, 5]
BBB -- [5, 2, 1, 2, 4, 5, 4, 4, 1, 2, 2, 2, 4, 4, 4, 3, 1, 2, 3, 3, 2]
inputlist=['AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5', 'BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2', 'K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1']
for item in inputlist:
item_to_list=item.split(" ")
temp_list=[int(i) for i in list(filter(None, item_to_list[2:]))]
print("{0} -- {1}".format(item_to_list[0],str(temp_list)))
Output:
AAAAA -- [4, 2, 1, 2, 4, 2, 4, 4, 5, 2, 2, 1, 5, 2, 4, 3, 1, 1, 3, 3, 5]
BBB -- [5, 2, 1, 2, 4, 5, 4, 4, 1, 2, 2, 2, 4, 4, 4, 3, 1, 2, 3, 3,2]
K -- [4, 1, 2, 1, 2, 1, 2, 5, 1, 1, 1, 1, 4, 2, 2, 1, 5, 1, 3, 4, 1]
Try this:
name=["AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5",
"BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2",
"K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1"]
for item in name:
thelist = list(map(int, ','.join(item.split(' ')[1:]).split(',')))
print(f"{item.split(' ')[0]} -- {thelist}")
output:
AAAAA -- [4,2,1,2,4,2,4,4,5,2,2,1,5,2,4,3,1,1,3,3,5]
BBB -- [5,2,1,2,4,5,4,4,1,2,2,2,4,4,4,3,1,2,3,3,2]
K -- [4,1,2,1,2,1,2,5,1,1,1,1,4,2,2,1,5,1,3,4,1]
x = ['AAAAA 4 2 1 2 4 2 4 4 5 2 2 1 5 2 4 3 1 1 3 3 5', 'BBB 5 2 1 2 4 5 4 4 1 2 2 2 4 4 4 3 1 2 3 3 2', 'K 4 1 2 1 2 1 2 5 1 1 1 1 4 2 2 1 5 1 3 4 1']
for i in x:
i = i.split(' ')
tmp = {i[0]:[int(items) for items in i[1:]]}
for i, j in tmp.items():
print(f"{i} - {j}")
Output:
AAAAA - [4, 2, 1, 2, 4, 2, 4, 4, 5, 2, 2, 1, 5, 2, 4, 3, 1, 1, 3, 3, 5]
BBB - [5, 2, 1, 2, 4, 5, 4, 4, 1, 2, 2, 2, 4, 4, 4, 3, 1, 2, 3, 3, 2]
K - [4, 1, 2, 1, 2, 1, 2, 5, 1, 1, 1, 1, 4, 2, 2, 1, 5, 1, 3, 4, 1]
you can make a dict, and also use that dict to get your specific output if that's what you want:
assuming your list is called full_list
lists = [sub.split() for sub in full_list]
keys = [l[0] for l in lists]
vals = [list(map(int,l[1:])) for l in lists]
d = {k:v for k,v in zip(keys,vals)}
if desired to get that specific output:
for k,v in d.items():
print(f'{k} -- {v}')
output:
AAAAA -- [4, 2, 1, 2, 4, 2, 4, 4, 5, 2, 2, 1, 5, 2, 4, 3, 1, 1, 3, 3, 5]
BBB -- [5, 2, 1, 2, 4, 5, 4, 4, 1, 2, 2, 2, 4, 4, 4, 3, 1, 2, 3, 3, 2]
K -- [4, 1, 2, 1, 2, 1, 2, 5, 1, 1, 1, 1, 4, 2, 2, 1, 5, 1, 3, 4, 1]
I want to create a simple vector of many repeated values. This is easy in R:
> numbers <- c(rep(1,5), rep(2,4), rep(3,3))
> numbers
[1] 1 1 1 1 1 2 2 2 2 3 3 3
However, if I try to do this in Python using pandas and numpy, I don't quite get the same thing:
numbers = pd.Series([np.repeat(1,5), np.repeat(2,4), np.repeat(3,3)])
numbers
0 [1, 1, 1, 1, 1]
1 [2, 2, 2, 2]
2 [3, 3, 3]
dtype: object
What's the R equivalent in Python?
Just adjust how you use np.repeat
np.repeat([1, 2, 3], [5, 4, 3])
array([1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3])
Or with pd.Series
pd.Series(np.repeat([1, 2, 3], [5, 4, 3]))
0 1
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 2
9 3
10 3
11 3
dtype: int64
That said, the purest form to replicate what you've done in R is to use np.concatenate in conjunction with np.repeat. It just isn't what I'd recommend doing.
np.concatenate([np.repeat(1,5), np.repeat(2,4), np.repeat(3,3)])
array([1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3])
Now you can use the same syntax in python:
>>> from datar.base import c, rep
>>>
>>> numbers = c(rep(1,5), rep(2,4), rep(3,3))
>>> print(numbers)
[1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3]
I am the author of the datar package. Feel free to submit issues if you have any questions.