Создание пустой Pandas DataFrame, а затем ее заполнение?
Я начинаю с документов панд на DataFrame здесь: http://pandas.pydata.org/pandas-docs/stable/dsintro.html
Я хотел бы итеративно заполнять DataFrame значениями для расчета временных рядов. В общем, я хотел бы инициализировать DataFrame столбцами A, B и строками отметок времени, все 0 или все NaN.
Затем я добавляю начальные значения и просматриваю эти данные, вычисляя новую строку из row[A][t] = row[A][t-1]+1
строки, скажем, row[A][t] = row[A][t-1]+1
или около того.
В настоящее время я использую код, как показано ниже, но я чувствую себя немного уродливо, и должен быть способ сделать это напрямую с помощью DataFrame, или просто лучше. Примечание: я использую Python 2.7.
import datetime as dt
import pandas as pd
import scipy as s
if __name__ == '__main__':
base = dt.datetime.today().date()
dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
dates.sort()
valdict = {}
symbols = ['A','B', 'C']
for symb in symbols:
valdict[symb] = pd.Series( s.zeros( len(dates)), dates )
for thedate in dates:
if thedate > dates[0]:
for symb in valdict:
valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]
print valdict
Ответы
Ответ 1
Вот несколько предложений:
Используйте date_range
для индекса:
import datetime
import pandas as pd
import numpy as np
todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')
columns = ['A','B', 'C']
Примечание. Мы могли бы создать пустой DataFrame (с NaN
s), просто написав:
df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs
Чтобы выполнить эти типы вычислений для данных, используйте массив numpy:
data = np.array([np.arange(10)]*3).T
Следовательно, мы можем создать DataFrame:
In [10]: df = pd.DataFrame(data, index=index, columns=columns)
In [11]: df
Out[11]:
A B C
2012-11-29 0 0 0
2012-11-30 1 1 1
2012-12-01 2 2 2
2012-12-02 3 3 3
2012-12-03 4 4 4
2012-12-04 5 5 5
2012-12-05 6 6 6
2012-12-06 7 7 7
2012-12-07 8 8 8
2012-12-08 9 9 9
Ответ 2
Если вы просто хотите создать пустой кадр данных и заполнить его некоторыми входящими кадрами данных, попробуйте следующее:
В этом примере я использую этот pandas doc для создания нового фрейма данных, а затем используя append для записи в newDF с данными из oldDF.
Посмотрите на это
newDF = pd.DataFrame() #creates a new dataframe that empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional
- Если мне придется добавлять новые данные в этот новый DF из более чем
один oldDFs, я просто использую цикл for для итерации
pandas.DataFrame.append()
Ответ 3
Если вы хотите, чтобы имена столбцов были на месте с самого начала, используйте этот подход:
import pandas as pd
col_names = ['A', 'B', 'C']
my_df = pd.DataFrame(columns = col_names)
my_df
Если вы хотите добавить запись в фрейм данных, лучше использовать:
my_df.loc[len(my_df)] = [2, 4, 5]
Вы также можете передать словарь:
my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic
Однако, если вы хотите добавить другой фрейм данных в my_df, сделайте следующее:
col_names = ['A', 'B', 'C']
my_df2 = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)
Если вы добавляете строки в цикл, учтите проблемы с производительностью:
Примерно для первых 1000 записей "my_df.loc" производительность лучше, но постепенно она становится медленнее с увеличением количества записей в цикле.
Если вы планируете делать все внутри большого цикла (скажем, 10 миллионов записей или около того):
Вам лучше использовать смесь этих двух; заполняйте фрейм данных iloc, пока размер не достигнет 1000, затем добавьте его к исходному фрейму данных и очистите временный фрейм данных. Это повысит вашу производительность примерно в 10 раз.
Ответ 4
Единственный правильный способ создания DataFrame
Большинство ответов здесь расскажут вам, как создать пустой DataFrame и заполнить его, но никто не скажет вам, что это плохо.
Вот мой совет: подождите, пока вы не убедитесь, что у вас есть все данные, с которыми вам нужно работать. Используйте список для сбора ваших данных, затем инициализируйте DataFrame, когда будете готовы.
data = []
for a, b, c in some_function_that_yields_data():
data.append([a, b, c])
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
Всегда дешевле добавить в список и создать DataFrame за один раз, чем создать пустой DataFrame (или один из NaN) и добавлять к нему снова и снова. Списки также занимают меньше памяти и представляют собой гораздо более легкую структуру данных для работы, добавления и удаления (при необходимости).
Другое преимущество этого метода заключается в том, что dtypes
автоматически выводятся (вместо того, чтобы назначать object
всем).
Последнее преимущество заключается в том, что RangeIndex
автоматически создается для ваших данных, поэтому беспокоиться об этом будет меньше (посмотрите на плохие методы append
и loc
ниже, вы увидите элементы в обоих, которые требуют соответствующей обработки индекса).
То, что вы не должны делать
append
или concat
внутри цикла
Вот самая большая ошибка, которую я видел от новичков:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # yuck
# or similarly,
# df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)
Память перераспределяется для каждой concat
вас операции append
или concat
. Соедините это с циклом, и вы получите квадратичную операцию сложности. Если вы мне не верите, прочитайте некоторые комментарии под другими ответами.
По моему опыту, создание фрейма данных необходимого размера, заполненного NaN, а затем заполнение значениями происходит намного-намного медленнее, чем создание фрейма данных [..] и присоединение одного столбца за каждый оборот цикла. Я имею в виду df[col_name] = pandas.Series([...])
в цикле, повторяющем имена столбцов. В первом случае не только выделение памяти занимает много времени, но замена NaN новыми значениями кажется чрезвычайно медленной. - deeenes
Обратите внимание, что append
(и аналогично concat
) копирует полный набор данных в новый объект каждый раз, следовательно, повторение и добавление может и приведет к значительному снижению производительности. - МустафаАатта
Другая ошибка, связанная с df.append
заключается в том, что пользователи склонны забывать, что append не является функцией на месте, поэтому результат должен быть возвращен обратно. Вы также должны беспокоиться о dtypes:
df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)
df.dtypes
A object # yuck!
B float64
C object
dtype: object
Работа со столбцами объекта никогда не бывает хорошей, потому что панды не могут векторизовать операции над этими столбцами. Вам нужно будет сделать это, чтобы это исправить:
df.infer_objects().dtypes
A int64
B float64
C object
dtype: object
loc
внутри цикла
Я также видел, что loc
используется для добавления в DataFrame, который был создан пустым:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df.loc[len(df)] = [a, b, c]
Как и раньше, вы не выделяете заранее необходимый объем памяти каждый раз, поэтому объем памяти увеличивается каждый раз, когда вы создаете новую строку. Это так же плохо, как append
, и даже более уродливо.
Пустой фрейм данных NaNs
И затем, создание DataFrame из NaN, и все оговорки, связанные с ним.
df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
A B C
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN
4 NaN NaN NaN
Он создает DataFrame столбцов объекта, как и другие.
df.dtypes
A object # you DON'T want this
B object
C object
dtype: object
В приложении есть все проблемы, описанные выше.
for i, (a, b, c) in enumerate(some_function_that_yields_data()):
df.iloc[i] = [a, b, c]
Доказательство в пудинге
Сроки этих методов - самый быстрый способ узнать, насколько они различаются с точки зрения их памяти и полезности.
![enter image description here]()
Контрольный код для справки.
Ответ 5
Предположим, датафрейм с 19 строками
index=range(0,19)
index
columns=['A']
test = pd.DataFrame(index=index, columns=columns)
Сохранение столбца А в качестве константы
test['A']=10
Сохранение столбца b как переменной, заданной циклом
for x in range(0,19):
test.loc[[x], 'b'] = pd.Series([x], index = [x])
Вы можете заменить первый x в pd.Series([x], index = [x])
любым значением