Moving elements in dictionary python to another index - python

If i have a dictionary like this for example:
dicta={1:['a','a','a'],2:['b,'b','b'],'N':['n','n','n'],3:['c','c','c']}
and i want the N to be in the last position as i convert this dict later on into a df. Is there a way to shift it down?
Finding the index of the N is fine: index=list(dicta.keys()).index('N')
but then how would you do the (in pseudo code) dicta.position[-1] = dicta[index] bit?

If you're using CPython 3.6+, since dict are insertion-based ordered, you can move an item to the end by popping it and then re-assigning it to the dictionary.
>>> dicta = {1: 'a', 2: 'b', 'N': 'n', 3: 'c'}
>>> dicta['N'] = dicta.pop('N')
>>> dicta
{1: 'a', 2: 'b', 3: 'c', 'N': 'n'}
If you're using lower versions then you're outta luck!

It can also be done with the collections.OrderedDict and its method OrderedDict.move_to_end() with keyword argument last set to True.

When the order of the dictionaty cannot be relied on (Python <3.7) you also should make sure the numbers are sorted. You could take the keys, remove the 'N', sort the remaining keys, and append the 'N' afterwards. Then use this list as explicit column argument to the DataFrame:
In [16]: dicta = {1:['a','a','a'], 2:['b','b','b'],
...: 'N': ['n','n','n'], 3:['c','c','c']}
In [17]: columns = list(dicta.keys())
In [18]: columns.remove('N')
In [19]: columns.sort()
In [20]: columns.append('N')
In [21]: pd.DataFrame(dicta, columns=columns)
Out[21]:
1 2 3 N
0 a b c n
1 a b c n
2 a b c n

Related

spliting values in a dictionary into fragments and making new values

dict={a:qwertyuiop} dict1={a:qw,b:er,c:ty,d:ui,e:op}
I want to create dict 1 from dict with splitting the value with length of 2
I have tried
value1=dict.value()
value2=value1.split(2)
It does not accept integer and I obviously using the wrong function, I have searched on the net but could not find it, which function should I use?
# Defining variables
d = {'a': 'abcde', 'b': 'cdefghi'}
n = 2
# One-Liner:
d1 = dict([(i + j*len(d), word) for j, key in enumerate(d.keys()) for i, word in enumerate([d[key][i:i+n] for i in range(0, len(d[key]), n)])])
print(d1)
# Normal code
d2 = dict()
for j, key in enumerate(d.keys()): # Enumerating threw the keys
for i, word in enumerate([d[key][i:i + n] for i in range(0, len(d[key]), n)]): # Enumerating threw n-characters at a time
d2[i + j*len(d)] = word # Assigning to the right key with math
print(d2)
One downside to this code is that we are losing the keys,
This has to be done in order to keep having only one key per value.
Output for d1: {0: 'ab', 1: 'cd', 2: 'cd', 3: 'ef', 4: 'gh', 5: 'i'}
Output for d2: {0: 'ab', 1: 'cd', 2: 'cd', 3: 'ef', 4: 'gh', 5: 'i'}
This function allows you to do exactly that, and gives you the choice of integer keys or letter keys by typing int or chr as the third function argument:
def ds(d,n,v=chr):
return({v(int(y/n)+[96 if v==chr else 0][0]):"".join([str(d[z]) for z in d])[y-n:y] for y in range(n,len("".join([d[z] for z in d]))+n,n)})
This works by first iterating through the dictionary values and returning the value of each key (in the str(d[z]) for z in d). The function then joins the list of string values together, (the "".join part), and then parses through the length that string (the for y in range(...) part) and returns a dictionary with values split every nth time.
Examples:
a=ds(myDictionary,2) #split every second character (string keys)
print(a)
#{'a': 'qw', 'b': 'er', 'c': 'ty', 'd': 'ui', 'e': 'op'}
b=ds(myDictionary,3,int) #split every third (integer keys)
print(b)
#{1: 'qwe', 2: 'rty', 3: 'uio', 4: 'p'}
c=ds(myDictionary,56,char) #split every fifty-sixth (string keys)
print(c)
#{'a': 'qwertyuiop'}
Also, no outside modules required! This is all built-in stuff.

Create a dictionary using key sets

I have 2 dictionary:
a = {'a':5, 'b':3, 'c':1}
b = {"ca":10, "sd":4, "aa":2}
What I want to obtain is:
z = {'a':"ca", 'b':"sd", 'c':"aa"}
How can I do this?
Edit:
I want to match the 1st key of a with the 1st key of b, the 2nd of a with the 2nd of b and so on.
In a (now edited into ambiguity) comment you suggested that the ordering you had in mind was by "frequency". Interpreting that as meaning ordering by dictionary value, you could make a new dict from zipping the keys sorted by the corresponding value:
In [14]: dict(zip(sorted(a, key=a.get), sorted(b, key=b.get)))
Out[14]: {'a': 'ca', 'b': 'sd', 'c': 'aa'}
This works because a.get is a method which gives us the values, so when we sort a (iteration of which is over the keys), we get them ordered by increasing value.
In [15]: sorted(a, key=a.get)
Out[15]: ['c', 'b', 'a']
This doesn't specify what to do in case of ties, though. To handle that you could sort the argument to sorted (e.g. sorted(sorted(a),key=a.get))) or use a key function (e.g. sorted(a, key=lambda x: (a[x], x))) so that at least the output is deterministic.
Try this:
a = {'a':5, 'b':3, 'c':1}
b = {"ca":10, "sd":4, "aa":2}
print {a.keys()[i]:b.keys()[i] for i in range(len(a.keys()))}
In that case you need to use OrderedDict to preserve the order. Here is an example:
import collections
import itertools
a = collections.OrderedDict()
b = collections.OrderedDict()
# add the data based on the order that you need
a['a'] = 5
a['b'] = 3
a['c'] = 1
b["ca"] = 10
b["sd"] = 4
b["aa"] = 2
# put them together. I user izip and iterkeys assuming you have a large data set
# also assuming the order in the new dictionary doesn't matter otherwise you have to use OrderedDict again.
z = {i: j for i, j in itertools.izip(a.iterkeys(), b.iterkeys())}
print z
>> {'a': 'ca', 'c': 'aa', 'b': 'sd'}

Issue with Nested Dictionaries in Python

I have some dictionary a.
a = {1: 'a', 2: 'b'}
And I had some dictionary b with a as a value
b = {1: a}
If I print b, change a then print b again, for example:
print(b)
a[1] = 'd'
print(b)
I get the following:
{'a': {1: 'a', 2: 'b'}}
{'a': {1: 'd', 2: 'b'}}
Why does this happen? Does the dict automatically update if you set a value to a variable and then update it? Thanks.
If you write,
b = {1: a}
the value of 1, that is a, refers to the dictionary that you previously defined. So whatever change that you make to dictionary a will be reflected in dictionary b. The literal a in dictionary b is just a reference object to dictionary a.
a, a dict, holds reference to the dictionary {1: 'a', 2: 'b'}. any changes that you make reflect in the dictionary.
since everything in python is an object, implies that every variable
is just a reference.
Hence due to the change in dict after the first print(b) the second print(b) is different.

Reformatting a dict where the values have a dict-like relationship

I have a defaultdict that looks like this:
d = { 'ID_001': ['A', 'A_part1', 'A_part2'],
'ID_002': ['A', 'A_part3'],
'ID_003': ['B', 'B_part1', 'B_part2', 'A', 'A_part4'],
'ID_004': ['C', 'C_part1', 'A', 'A_part5', 'B', 'B_part3']
}
Before I go any further, I have to say that A_part1 isn't the actual string -- the strings are really a bunch of alphanumeric characters; I represented it as such to show that A_part1 is text that is associated with A, if you see what I mean.)
Standing back and looking at it, what I really have is a dict where the values have their own key/value relationship, but that relationship exists only in the order they appear in, in the list.
I am attempting to end up with something like this:
['ID_001 A A_part1, A_part2',
'ID_002 A A_part3',
'ID_003 B B_part1 B_part2',
'ID_003 A A_part4',
'ID_004 C C_part1',
'ID_004 A A_part5',
'ID_004 B B_part3']
I have made a variety of attempts; I keep wanting to run through the dict's value, making note of the character in the first position (eg, the A), and collect values until I find a B or a C, then stop collecting. Then append what I have to a list that I have declared elsewhere. Ad nauseum.
I'm running into all sorts of problems, not the least of which is bloated code. I'm missing the ability to iterate through the value in a clean way. Invariably, I seem to run into index errors.
If anyone has any ideas/philosophy/comments I'd be grateful.
What about something like:
d = { 'ID_001': ['A', 'A_part1', 'A_part2'],
'ID_002': ['A', 'A_part3'],
'ID_003': ['B', 'B_part1', 'B_part2', 'A', 'A_part4'],
'ID_004': ['C', 'C_part1', 'A', 'A_part5', 'B', 'B_part3']
}
def is_key(s):
return s in ['A','B','C']
out = {}
for (k,v) in d.iteritems():
key = None
for e in v:
if is_key(e): key = e
else:
out_key = (k,key)
out[out_key] = out.get(out_key, []) + [e]
which generates:
{('ID_001', 'A'): ['A_part1', 'A_part2'],
('ID_002', 'A'): ['A_part3'],
('ID_003', 'A'): ['A_part4'],
('ID_003', 'B'): ['B_part1', 'B_part2'],
('ID_004', 'A'): ['A_part5'],
('ID_004', 'B'): ['B_part3'],
('ID_004', 'C'): ['C_part1']}
It's important that you update the is_key function to match your actual input.
Also, the variable names are far from optimal, but I'm not really sure what you're doing -- you should be able to (and should) give them more appropriate names.
May not be in the order you want, but no thanks for further headaches.
d = { 'ID_001': ['A', 'A_part1', 'A_part2'],
'ID_002': ['A', 'A_part3'],
'ID_003': ['B', 'B_part1', 'B_part2', 'A', 'A_part4'],
'ID_004': ['C', 'C_part1', 'A', 'A_part5', 'B', 'B_part3']
}
rst = []
for o in d:
t_d={}
for t_o in d[o]:
if not t_o[0] in t_d:
t_d[t_o[0]] = [t_o]
else: t_d[t_o[0]].append(t_o)
for t_o in t_d:
rst.append(' '.join([o,t_d[t_o][0],', '.join(t_d[t_o][1:])]))
print(rst)
https://ideone.com/FeBDLA
['ID_004 C C_part1', 'ID_004 A A_part5', 'ID_004 B B_part3', 'ID_003 A A_part4', 'ID_003 B B_part1, B_part2', 'ID_002 A A_part3', 'ID_001 A A_part1, A_part2']
Whenever you're trying to do something involving contiguous groups, you should think of itertools.groupby. You weren't very specific about what condition separates the groups, but if we take "the character in the first position" at face value:
from itertools import groupby
new_list = []
for key, sublist in sorted(d.items()):
for _, group in groupby(sublist, key=lambda x: x[0]):
new_list.append(' '.join([key] + list(group)))
produces
>>> for elem in new_list:
... print(elem)
...
ID_001 A A_part1 A_part2
ID_002 A A_part3
ID_003 B B_part1 B_part2
ID_003 A A_part4
ID_004 C C_part1
ID_004 A A_part5
ID_004 B B_part3

Python dictionary.keys() error

I am trying to use the .keys() and instead of getting a list of the keys like
always have in the past. However I get this.
b = { 'video':0, 'music':23 }
k = b.keys()
print( k[0] )
>>>TypeError: 'dict_keys' object does not support indexing
print( k )
dict_keys(['music', 'video'])
it should just print ['music', 'video'] unless I'm going crazy.
What's going on?
Python 3 changed the behavior of dict.keys such that it now returns a dict_keys object, which is iterable but not indexable (it's like the old dict.iterkeys, which is gone now). You can get the Python 2 result back with an explicit call to list:
>>> b = { 'video':0, 'music':23 }
>>> k = list(b.keys())
>>> k
['music', 'video']
or just
>>> list(b)
['music', 'video']
If you assigned k like so:
k = list(b.keys())
your code will work.
As the error says, the dict_keys type does not support indexing.
This is one of the breaking changes between Python 2 and 3.
In Python 2:
>>> help(dict.keys)
keys(...)
D.keys() -> list of D's keys
In Python 3:
>>> help(dict.keys)
keys(...)
D.keys() -> a set-like object providing a view on D's keys
This change in behavior makes a lot of sense since a dict is semantically unordered and its keys are unique - just like a set.
This change means that you don't have to create a new list of keys every time you want to do some kind of set comparison with a dict's keys.
Getting the same behavior in 2 and 3
To help transition to Python 3, Python 2.7 has another dict method, viewkeys. The viewkeys method is most similar to Python 3's dict.keys method:
>>> d
{'a': None, 'c': None, 'b': None, 'd': None}
>>> for k in d.viewkeys(): print k
...
a
c
b
d
>>> d.viewkeys() & set('abc')
set(['a', 'c', 'b'])
In Python 3, the closest analog to the old behavior is to pass dict.keys() to list:
>>> d
{'d': None, 'a': None, 'c': None, 'b': None}
>>> list(d.keys())
['d', 'a', 'c', 'b']
Or just pass the dict to list, since a dict will iterate over its keys anyways:
>>> list(d)
['d', 'a', 'c', 'b']
You could create a utility functions to abstract the behavior over 2 and 3:
if hasattr(dict, 'viewkeys'): # Python 2.7
def keys(d):
return d.viewkeys()
else: # Python 3
def keys(d):
return d.keys()
And pass a dict to list to get the list form, and in both 2 and 3, you'll get the same output:
>>> d
{'b': None, 'a': None, 'c': None, 'd': None}
>>> keys(d)
dict_keys(['b', 'a', 'c', 'd'])
>>> list(d)
['b', 'a', 'c', 'd']
If you simply want a list of keys from a dictionary you can directly do like this:
b = {"name": "xyz", "class":"abc", "college": "qwert"}
key_list = list(b)
key_list will contain all the key names as a list, though, this will not repeats a key, if found more than once. Duplicate keys will be counted as one.
import random
b = { 'video':0, 'music':23,"picture":12 }
random.choice(tuple(b.items()))
# Returns a random dictionary entry as a tuple:
# ('music', 23)

Categories

Resources