python pandas – Редактирование нескольких DataFrames с циклом for

Учитывая следующие 2 списка из 3-х и 3-х пустых DataFrames

dict0={'actual': {'2013-02-20 13:30:00': 0.93}} dict1={'actual': {'2013-02-20 13:30:00': 0.85}} dict2={'actual': {'2013-02-20 13:30:00': 0.98}} dicts=[dict0, dict1, dict2] df0=pd.DataFrame() df1=pd.DataFrame() df2=pd.DataFrame() dfs=[df0, df1, df2] 

Я хочу рекурсивно изменить 3 Dataframes в цикле, используя следующую строку:

 for df, dikt in zip(dfs, dicts): df = df.from_dict(dikt, orient='columns', dtype=None) 

Однако при попытке получить, например, 1 из df вне цикла, он все еще пуст

 print (df0) 

вернется

 Empty DataFrame Columns: [] Index: [] 

При печати df из цикла for мы можем видеть, что данные правильно добавлены.

Как сделать цикл так, чтобы можно было напечатать 3 dfs с их изменениями вне цикла?

В вашем цикле df является лишь временным значением, а не ссылкой на соответствующий элемент списка. Если вы хотите изменить список во время его итерации, вам нужно ссылаться на список по индексу. Вы можете сделать это, используя перечисление Python:

 for i, (df, dikt) in enumerate(zip(dfs, dicts)): dfs[i] = df.from_dict(dikt, orient='columns', dtype=None) 

Это будет сделано на месте!
Обратите внимание на 3 восклицания

один лайнер

 [dfs[i].set_value(r, c, v) for i, dn in enumerate(dicts) for r, dr in dn.items() for c, v in dr.items()]; 

несколько более интуитивно понятный

 for d, df in zip(dicts, dfs): temp = pd.DataFrame(d).stack() for (r, c), v in temp.iteritems(): df.set_value(r, c, v) df0 actual 2013-02-20 13:30:00 0.93 

эквивалентная альтернатива
без конструкции pd.DataFrame

 for i, dn in enumerate(dicts): for r, dr in dn.items(): for c, v in dr.items(): dfs[i].set_value(r, c, v) 

Почему это другое?
Все остальные ответы, до сих пор, переназначают новый фрейм данных в требуемое положение в списке данных. Они склеивают данные, которые были там. Исходный dataframe остается пустым, в то время как новый непустой находится в списке.

Это решение изменяет структуру данных, гарантируя, что исходный фреймворк обновляется с новой информацией.

По ОП:

Однако при попытке получить, например, 1 из df вне цикла, он все еще пуст


синхронизация
Это также значительно быстрее

введите описание изображения здесь


настроить

 dict0={'actual': {'2013-02-20 13:30:00': 0.93}} dict1={'actual': {'2013-02-20 13:30:00': 0.85}} dict2={'actual': {'2013-02-20 13:30:00': 0.98}} dicts=[dict0, dict1, dict2] df0=pd.DataFrame() df1=pd.DataFrame() df2=pd.DataFrame() dfs=[df0, df1, df2] 

Вам нужно сохранить ссылку на объекты df, чтобы вы могли попробовать:

 for idx, dikt in enumerate(dicts): dfs[idx] = dfs[idx].from_dict(dikt, orient='columns', dtype=None) 

У меня нет объяснений, почему это так. Однако обходной путь:

 dict0={'actual': {'2013-02-20 13:30:00': 0.93}} dict1={'actual': {'2013-02-20 13:30:00': 0.85}} dict2={'actual': {'2013-02-20 13:30:00': 0.98}} dicts=[dict0, dict1, dict2] dfs = [] for dikt in dicts: df = df.from_dict(dikt, orient='columns', dtype=None) dfs.append(df) 

Теперь

 dfs[0] 

возвращается

  actual 2013-02-20 13:30:00 0.93 

Один лайнер.

 >>>df_list = [df.from_dict(dikt, orient='columns', dtype=None) for (df, dikt) in zip(dfs, dicts)] >>>df_list [ actual 2013-02-20 13:30:00 0.93, actual 2013-02-20 13:30:00 0.85, actual 2013-02-20 13:30:00 0.98] >>>df_list[0] actual 2013-02-20 13:30:00 0.93