#python #pandas #dataframe #for-loop #concatenation
#python #pandas #фрейм данных #для цикла #конкатенация
Вопрос:
Я пытаюсь создать список фреймов данных в цикле for, а затем объединить их вне цикла for и записать в Excel. Я получил близкий код, но по какой-то причине столбец, созданный внутри цикла for, оказывается конечным значением, а не каждым отдельным значением по мере его прохождения. Я уверен, что это очень просто, и я просто упускаю что-то простое, но, похоже, не могу понять это сегодня вечером. Вот некоторый фиктивный код для иллюстрации и помощи в решении проблем. В конце я хотел бы получить вывод Excel с wks 1-9. Однако в моем фактическом выводе все значения в столбце wk равны 9.
import pandas as pd
sample = []
area = pd.Series({'California':423967, 'Texas':695662})
pop = pd.Series({'California':38332521, 'Texas':26448193})
data = pd.DataFrame({'area':area, 'pop':pop})
print(data)
for i in range(10):
data['wk'] = i
sample.append(data)
print(data)
res = pd.concat(sample)
res.to_excel("Concatenating DataFrames.xlsx", index=False)
Комментарии:
1. data[‘wk’] — это столбец, а не элемент, но вы пытаетесь присвоить ему одно значение, в этом случае pandas заполнит все строки столбца одним и тем же значением.
2. Я не уверен, что точно понимаю. Я знаю, что это колонна. Однако я подумал, что, записав его в список фреймов данных, а затем объединив их, он сохранит свою ценность. Например, когда я печатаю (данные), он показывает первый фрейм данных с неделей 1, второй с неделей 2 и т.д. Как мне сохранить эти значения при окончательном объединении списка фреймов данных вместе?
Ответ №1:
Проблема заключается в том, что когда вы добавляете данные в список, это не создает для них отдельной памяти, скорее все они ссылаются на одну и ту же память, поэтому после последнего обновления в цикле оно становится 9 или конечным значением.
просто замените
sample.append(data)
с
sample.append(data.copy())
.copy() принудит pandas создавать новую память для каждого df в цикле
Комментарии:
1. Я не программист по профессии, но есть ли какие-нибудь рекомендации по изучению памяти и распределению памяти? Я ошибочно предположил, что он будет записывать фрейм данных в список каждый раз, таким образом сохраняя любое значение недели, которое имел фрейм данных. Очевидно, я был неправ, но был бы признателен за любые мысли или советы, чтобы лучше понять, почему это происходит, и понять распределение памяти / памяти.
Ответ №2:
Создание нескольких фреймов данных в цикле и их объединение очень неэффективно. Лучше выполнить итерацию по спискам или словарям, а затем создать один фрейм данных после цикла. Ниже я преобразовал вашу серию обратно в словари для этой цели. Обратите внимание, что словари должны копироваться на каждой итерации цикла, чтобы цикл не продолжал изменять исходные словари.
import pandas as pd
import openpyxl
from copy import deepcopy
area = pd.Series({'California':423967, 'Texas':695662})
pop = pd.Series({'California':38332521, 'Texas':26448193})
area_d = area.to_dict()
pop_d = pop.to_dict()
sample = []
for i in range(10):
area_copy = deepcopy(area_d)
pop_copy = deepcopy(pop_d)
area_copy['wk'] = i
pop_copy['wk'] = i
sample = [area_copy, pop_copy]
df = pd.DataFrame(sample)
df.to_excel("result.xlsx", index = False)
Комментарии:
1. Я вижу, что это работает, когда область и pop являются статическими. В моем реальном сценарии базовые данные изменяются. Например, он агрегирует продажи по первой неделе и вычисляет среднее значение и ранг. Затем он повторяет цикл во второй раз, извлекая данные с 1-2-й недели, и повторяет процесс и т. Д. Через несколько недель. Будет ли этот сценарий работать для этого? Я предполагаю, что нет, потому что area и pop в этом примере будут меняться с каждым циклом for . Вот почему я создал список фреймов данных для объединения вне цикла, но я был бы рад услышать более эффективные способы использования памяти, поскольку я все еще учусь.
2. @ShawnSchreier Я совершенно уверен, что это сработает. Приведите пример, который более реалистично отражает ваш рабочий процесс, и мы сможем его рассмотреть.