0

I have a list of dict1.keys() I'm enumerating over and I'd like to use the element as a string.

for i,j in enumerate(dict1.keys()): str(j) = somethingElse
>>> SyntaxError: can't assign to function call

https://dbader.org/blog/python-enumerate describes the enumerate entities as a tuple of: (index, element). The type(j) is <class 'str'>, which I can print, but not use as a variable.

EDIT:

for i,j in enumerate(dict1.keys()): j = somethingElse

EDIT2: I think the problem may be with pandas. The first line works, not the second.

for i,j in enumerate(dict1.keys()): list1.append(j)
for i,k in enumerate(list1): k = pd.DataFrame(dict1[k]['Values'])

EDIT3: That second line does work, but only for only ends up with one df, with name 'k' instead of the key. But heres what Im trying to. Each dict converted to a df using its key name:

for i,j in enumerate(dict1.keys()): j = pd.DataFrame(dict1[j]['Values'])

EDIT4: According to the comments below, I switched to a for loop on the keys (which dont need to be explicitly called), but it still won't use the element 'i' as a variable. However, from the question linked below, elements are able to be used as a key in a dict. After reducing the question to "use list item as name for dataframe" and searching that, it verks. I'll post as an answer also:

dict2={}
for i in dict1: dict2[i] = pd.DataFrame(dict1[i]['Values'])

..thus the names are preserved. Actually, this is similar to Sheri's answer with lists, but the names retain association with the dfs. There may not be a way to set a variable value using something other than a plain string, but I'll start a different question for that.

use elements in a list for dataframe names

alchemy
  • 954
  • 10
  • 17
  • 1
    what you are trying to do in this line `str(j) = somethingElse` – Sheri Apr 02 '20 at 17:13
  • can you share your dictionary with us – Sheri Apr 02 '20 at 17:16
  • @sheri, Im trying to create pandas dataframes from dictionaries that are values of a higher dictionary of about 4 keys. its confusing, so I tried to make the question in general terms – alchemy Apr 02 '20 at 17:23
  • 1
    because you are generating your pandas dataframe dynamically inside a for loop so at the end when you print `k` it will show you the last generated dataframe. You should store your dataframe in list – Sheri Apr 02 '20 at 17:46
  • Try using this `for i,j in enumerate(dict.keys()): j = pd.DataFrame(dict[j]['Values']); listOfFrame.append(j)` – Sheri Apr 02 '20 at 17:48
  • Step back a moment and think about why you’re using `enumerate` here. Are you clear about the function’s purpose? What is it supposed to achieve here? – Konrad Rudolph Apr 02 '20 at 18:10

4 Answers4

1

Because you are generating your pandas dataframe dynamically inside a for loop so at the end when you print j it will show you the last generated dataframe. You should store your dataframe in list Try using this:

listOfFrame = [] 
for j in dict.keys(): 
    j = pd.DataFrame(dict[j]['Values'])
    listOfFrame.append(j)
Sheri
  • 1,383
  • 3
  • 10
  • 26
  • I thought it might have to be a two step process.. but more importantly, can I use the elementInStrForm as a name for a pandas dataframe.. I'm testing.. – alchemy Apr 02 '20 at 17:27
  • @alchemy you can easily do this – Sheri Apr 02 '20 at 17:29
  • 1
    thanks, see my EDIT2. It may be a problem with pandas or my syntax using it. – alchemy Apr 02 '20 at 17:35
  • actually, see Thomas's answer too.. it seems to be using the 'j' as a letter when assigning the variable value, not the enumerate element 'j'. I will try your code you pasted above. You can reply here and I see it. – alchemy Apr 02 '20 at 17:51
  • hmm, interesting.. that worked fairly well.. At least I have the data in the list1. The key names are the first 4 items, and the DataFrames are the last 4 items. strange.. but progress! thanks – alchemy Apr 02 '20 at 18:00
  • @alchemy pleasure to help you – Sheri Apr 02 '20 at 18:00
  • if you put that in your answer, I will accept.. unless there is another answer in the near future with a complete explanation of why it's doing that and the 'proper' solution. but for now, I can keep the project moving, thanks again! – alchemy Apr 02 '20 at 18:02
  • btw, I will probably just use `for i,j in enumerate(dict1.keys()): list1.append(pd.DataFrame(dict1[j]['Values']))` and refer to the dfs by their list and index. – alchemy Apr 02 '20 at 18:05
  • The use of `enumerate` still doesn’t make any sense whatsoever here. Nor, for this matter, does the use of `.keys()`. Both make the code more complicated than necessary. And finally this would normally be done without a loop in Python (e.g. using list comprehension instead). – Konrad Rudolph Apr 02 '20 at 18:10
  • 1
    @KonradRudolph, okay, then provide and answer using list comprehension. You could also explain why it is better than enumerate and keys, obviously starting with the fact that with enumerate you cant use the element as a regular variable. That actually makes sense in the context of having any other variables named i or j, where enumerate would have to decide whether to overwrite them. I think thats why my use of it doesnt work. Otherwise, it seems the most concise and readable formulation. oh, wait. .maybe you did.. – alchemy Apr 02 '20 at 19:56
0

Indeed j will be a str (or whatever else type of key you are using in dict).

The actual problem is with the loop body, as the error message states:

str(j) = somethingElse

is not valid Python. The left hand side is a call to the str function, so you cannot assign a value to it.

Thomas
  • 174,939
  • 50
  • 355
  • 478
0

Based on the comments you want neither enumerate nor to iterate over the dict keys. Instead, you want to iterate over its values:

dfs = []
for val in dict1.values():
    dfs.append(pd.DataFrame(val['Values']))

However, this would normally written without an explicit loop in Python, for instance by using list comprehension:

dfs = [pd.DataFrame(val['Values']) for val in dict1.values()]
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • yeah, I guess that would work. ..yes, this is the problem with the cantankerousness of `for i in range(len(list1)):..`, it makes people have to use Enumerate, and then forget the original meaning of `in`. They really should have made the same default behavior for lists as for dicts. `for i in list1: list1[i]`, no Enumerate necessary.. unless in specific cases.. = higher level language.. and less confusion. thanks ..it still might have variable collisions though. Does this work with `val = pd.DataFrame(val['Values'])` as the 3rd line without the list? That is where Enumerate is having problems. – alchemy Apr 02 '20 at 20:06
  • The for loop works the same as Enumerate, although more concise. It still doesnt allow the use of the element i as a variable. I'm trying to create several dfs with names instead of a list of unnamed dfs, because the names change and therefore their order in dict1.keys() and then the order of the dfs in the list1. Better to name them each, so I can call the df by its name. To do this efficiently in a loop, I need to be able to use the element i as a variable. Or maybe Ill have to rename them with the keys, inefficiently. – alchemy Apr 02 '20 at 20:51
  • @alchemy “It still doesnt allow the use of the element i as a variable.” — That’s a fundamental limitation of the language. You can’t (directly) use a “variable” variable. How would the language syntactically disambiguate this from a *regular* variable? The solution to this is precisely to use dicts, where you can use names as keys. – Konrad Rudolph Apr 03 '20 at 07:42
  • thanks, as I say in my new question (at top), Bash is able to do this. It just overwrites the *regular* variable. Dicts are less efficient, see the few answers to the Question mine was marked duplicate of. Others used objects and classes, also less efficient. But using the var() or global() functions is concise, and using `setattr(sys.modules[__name__], var_name, var_value)` might work for an element in a for loop. ..have to test that. – alchemy Apr 03 '20 at 17:57
  • @alchemy Bash only allows this because variable use in Bash is prefixed with `$`, whereas variable assignment and declaration aren’t. That’s how Bash can syntactically distinguish these cases. You can of course use `var` etc, but *these also use dicts internally*! – Konrad Rudolph Apr 03 '20 at 18:32
  • now, we're getting somewhere.. good point, but isnt it 'better' not to have to prefix with $? Why could variable assignment and declaration not be the same? Overwrite by default (without a 'noclobber' as in bash redirection). Interesting to know they are stored as dicts, makes sense. So why not allow variable assignment to a name that is not a plain string, but a reference to a plain string?.. seems functionally equivalent to me. – alchemy Apr 03 '20 at 18:49
  • @alchemy Again: how would you syntactically distinguish them?! One is written as `var = value`. And the other? Anyway, this doesn’t exist because it’s simply unnecessary: dictionaries solve the same problem and are *as efficient* (in fact they’re algorithmically optimally efficient under certain conditions, and every interpreter worth its salt uses them internally for variable name lookup). – Konrad Rudolph Apr 03 '20 at 19:17
  • distinguish what for? I dont follow.. just overwrite the variable name with the last used variable value. ..writing `for i in dict1: i = pd.dataframe()` is way more consise than `for i in dict1: dict[i] = pd.dataframe()` *and then not being able to call the dataframe simply by its name* instead having to use its ditc1['key'] every time. Im sure dicts are more efficient when iterating through a large number of keys, but it doesnt allow just calling a df by name. That simple functionality was lost somewhere, and is still valuable as most simple functionalities are for building more complex ones. – alchemy Apr 03 '20 at 19:31
  • @alchemy How is Python supposed to know that you want to assign to a variable whose name is given by the contents of `i`, rather than wanting to assign to the variable `i` itself? `i = pd.dataframe()` already has an existing meaning, you can’t just decide that under magical circumstances it means something else. – Konrad Rudolph Apr 03 '20 at 19:33
  • I guess its a matter proximity, or inside to out, as in arithmetic. `for i in dict1: i = value`. So by that convention the inner (or second) i (as its interpreted in its local context as resolved to its most plain expansion or dereferencing) would = the value, not the outer (or first) i. If that makes sense. I think thats what most would assume based on English lingual structure. ..if you say a 'cat named Felix' and then 'Felix is meowing' we don't interpret Felix as an entity in a set of names, but as the cat itself. – alchemy Apr 03 '20 at 20:33
  • Anyway, I think I've found out why in the Duplicate, Ill sum up. – alchemy Apr 03 '20 at 20:38
0

From the question linked below, elements are able to be used as a key in a dict. After reducing the question to "use list item as name for dataframe" and searching that, it verks. I'll post as an answer also:

dict2={}
for i in dict1: dict2[i] = pd.DataFrame(dict1[i]['Values'])

..thus the names are preserved. Actually, this is similar to Sheri's answer with lists, but the names retain association with the dfs. There may not be a way to set a variable value using something other than a plain string, but I'll start a different question for that.

use elements in a list for dataframe names

alchemy
  • 954
  • 10
  • 17