# Remove Rows from dictionary of dictionaries

I just lost my hope. After 20 min of trying to solve this exercise, I hit " see the answer" button. I don’t understand almost nothing from the answer

The full code is:

``````from numpy import nan

d = {
'method': {160: 'Transit',
506: 'Radial Velocity',
943: 'Pulsar Timing',
225: 'Radial Velocity',
741: 'Transit'},
'orbital_period': {160: 2.91626,
506: 4.6455,
943: 98.2114,
225: 1313.0,
741: 42.8961},
'mass': {160: nan,
506: 0.013000000000000001,
943: nan,
225: 0.63,
741: nan},
'distance': {160: 214.0,
506: 24.05,
943: nan,
225: 56.34,
741: nan}
}

#DQ answer:

def remove_keys(d, keys_to_remove):
return {k:v for k,v in d.items() if k not in keys_to_remove}

def remove_rows(d, rows):
return {col:remove_keys(value, rows) for col, value in d.items()}

#For output:
for column,values in remove_rows(d, [506, 225]).items():
print(column, values, sep="\n")
``````

I’d like someone to describe step by step what’s going on in this code.
Things that I don’t understand at all:

1. Why after the ‘return’ statement there are { … } in both definitions, what do they stand for?
2. Where “col” is defined or put to the parameters. How is it possible that it doesn’t produce error? And what actually this “col” is and how does it work ( and what colon do after “col”) ?
3. “Value” isn’t defined in the definition too. Same “k”, “v” above.
4. About “value” inside of the second definition: it seems to refer to “d” because remove_keys(d, keys_to_remove). Does it mean that value == d? If so, then why isn’t there punt d instead value in the second definition ?
5. Inside the parameters statements related to the list of rows in “def remove_rows”,rows are mentioned by " rows" parameter. Does it mean that one parameter can hold the whole list?( in this case, the list contains two rows: [506, 225]). What’s the limitation of capacity of one parameter? can it hold for ex a hole dictionary too?( Im asking in general, because till today I thought that one parameter could hold just one value and value only)
6. General question: Are there any other usages of each type of brackets that surround the entire code in the Return statement? I meant: {…} […] (…) <…>

I want to cry…

This is dictionary comprehension ! Same than list comprehension but for dictionary. Now I am sure you will look at it with new eyes

So now trying to answer each point:
1.Why after the ‘return’ statement there are { … } in both definitions, what do they stand for?
The function returns a dictionary.

2.Where “col” is defined or put to the parameters. How is it possible that it doesn’t produce error? And what actually this “col” is and how does it work ( and what colon do after “col”) ?
“col” here is just naming convention for the for loop. could have been any other word. Colon after col means variable col is holding a key of the dictionary you are creating with remove_rows function.
3. “Value” isn’t defined in the definition too. Same “k”, “v” above.
To understand it better: refer to https://realpython.com/iterate-through-dictionary-python/#iterating-through-items
4. About “value” inside of the second definition: it seems to refer to “d” because remove_keys(d, keys_to_remove). Does it mean that value == d? If so, then why isn’t there punt d instead value in the second definition ?
d here is also pure naming convention for a parameter.
5. Inside the parameters statements related to the list of rows in “def remove_rows”,rows are mentioned by " rows" parameter. Does it mean that one parameter can hold the whole list?( in this case, the list contains two rows: [506, 225]). What’s the limitation of capacity of one parameter? can it hold for ex a hole dictionary too?( Im asking in general, because till today I thought that one parameter could hold just one value and value only)
Yes a parameter can accept a list, or a dictionary or any kind of python object.

Adding @drill_n_bass that I am conscious that my explanations may be not very satisfactory because I am not a very good teacher but here there are fellows that will explain it much better, just a matter of time they will answer you!

it’s kind of true. Just realized that I’ve done more additional exercises than the basic programme of learning. This is the reason why so many things, suddenly, start to appear so unfamiliar. I didn’t learn about comprehension

1 Like

Probably, it will be more clear if you write your functions in this way (here I changed only variable names and will use them further in my explanations):

``````def remove_keys(d, keys_to_remove):
return {k:v for k,v in d.items() if k not in keys_to_remove}

def remove_rows(d, keys_to_remove):
return {k:remove_keys(v, keys_to_remove) for k,v in d.items()}
``````

Both of these functions return a dictionary comprehension, as @WilfriedF mentioned. The `items()` method of dictionaries, used in both functions, returns an object, containing the key-value pairs of the dictionary as a list of tuples. In each of these tuples, the first value is the key, the second value is the value (well, sounds a bit tautological ). Hence, the first function will return a new dictionary, composed by key: value pairs from the original dictionary `d` with only those keys that are not contained in the `keys_to_remove` list (and yes, an input parameter of a function can be easily a list or a dictionary).

Now about the second function. Here in the dictionary `d` each key has as a value another dictionary, and the whole structure actually represents tabular data (just look at the mission screen). With each iteration, we extract from the items of our “giant” dictionary (`d`) a key (`k`) and its correponding value `v` (which is also a dictionary), then we clean this “mini-dictionary” `v` using the first function (i.e., removing the keys that are present in the `keys_to_remove` list) and then we assign this cleaned mini-dictionary `v` back to its key `k`.

One more comment, about the DQ solution for this exercise. In the first function, the second input parameter is called `kews_to_remove`, in the second function the second input parameters is called `rows`. In my code, in both functions this thing is called `kews_to_remove`, and, functionally, it is the same thing indeed. If you look again at the explanations in that mission screen, about how dictionaries can represent tabular data, you will see that the keys of the giant dictionary represent column names and the values represent our mini-dictionaries `v` from the second function. In these mini-dictionaries, we see the same succession of the keys in each, and they actually represent the rows of the table, and the values for each represent just normal values from the table. That’s why the list called `rows` in the DQ solution contains the rows of table to be removed, but on the other hand, it contains the keys to be removed from each mini-dictionary.

1 Like

Is it common practice to include actual code in the return statement? It’s more concise, but it makes it harder to understand the code sometimes. Isn’t it better to solve the problem in separate lines of code, then assign the result to a variable and return it?

Check my alternative solution to this problem here. I think it’s more readable than the one provided by dataquest, no offense

Hi @zico333,

Good observation In case of long lines of code, as actually here, it’s better to assign it first to a variable (or even divide it into several consequent variables) and then return this variable. It will definitely be more readable, especially when the code is rather complicated.

And your solution looks really cool!

1 Like

And your solution looks really cool!

Thank you!

1 Like