Python pandas: заполняйте фрейм данных строка за строкой

133

Простая задача добавления строки к pandas.DataFrameобъекту кажется сложной. По этому поводу есть 3 вопроса о stackoverflow, ни один из которых не дает рабочего ответа.

Вот что я пытаюсь сделать. У меня есть DataFrame, форма которого я уже знаю, а также имена строк и столбцов.

>>> df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'])
>>> df
     a    b    c    d
x  NaN  NaN  NaN  NaN
y  NaN  NaN  NaN  NaN
z  NaN  NaN  NaN  NaN

Теперь у меня есть функция для итеративного вычисления значений строк. Как мне заполнить одну из строк словарем или буквой pandas.Series? Вот несколько неудачных попыток:

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df['y'] = y
AssertionError: Length of values does not match length of index

Видимо он пытался добавить столбец вместо строки.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.join(y)
AttributeError: 'builtin_function_or_method' object has no attribute 'is_unique'

Очень неинформативное сообщение об ошибке.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.set_value(index='y', value=y)
TypeError: set_value() takes exactly 4 arguments (3 given)

По-видимому, это только для установки отдельных значений в фрейме данных.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.append(y)
Exception: Can only append a Series if ignore_index=True

Что ж, я не хочу игнорировать индекс, иначе вот результат:

>>> df.append(y, ignore_index=True)
     a    b    c    d
0  NaN  NaN  NaN  NaN
1  NaN  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN
3    1    5    2    3

Он выровнял имена столбцов со значениями, но потерял метки строк.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.ix['y'] = y
>>> df
                                  a                                 b  \
x                               NaN                               NaN
y  {'a': 1, 'c': 2, 'b': 5, 'd': 3}  {'a': 1, 'c': 2, 'b': 5, 'd': 3}
z                               NaN                               NaN

                                  c                                 d
x                               NaN                               NaN
y  {'a': 1, 'c': 2, 'b': 5, 'd': 3}  {'a': 1, 'c': 2, 'b': 5, 'd': 3}
z                               NaN                               NaN

Это тоже с треском провалилось.

Итак, как вы это делаете ?

xApple
источник

Ответы:

92

df['y'] установит столбец

поскольку вы хотите установить строку, используйте .loc

Обратите внимание, что .ixэто эквивалентно здесь, у вас не получилось, потому что вы пытались назначить словарь каждому элементу строки, yвероятно, не то, что вы хотите; преобразование в серию сообщает пандам, что вы хотите выровнять ввод (например, тогда вам не нужно указывать все элементы)

In [7]: df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'])

In [8]: df.loc['y'] = pandas.Series({'a':1, 'b':5, 'c':2, 'd':3})

In [9]: df
Out[9]: 
     a    b    c    d
x  NaN  NaN  NaN  NaN
y    1    5    2    3
z  NaN  NaN  NaN  NaN
Джефф
источник
Понимаю. Итак, locатрибут фрейма данных определяет специальное значение, __setitem__которое, как я полагаю, творит чудеса.
xApple
Можете ли вы создать это за один проход (т.е. с помощью столбцов, индекса и y)?
Энди Хайден
5
Итак, если я могу генерировать по одной строке за раз, как мне оптимально построить фрейм данных?
xApple
Ожидал, что какой-то вариант df = pd.DataFrame({'y': pd.Series(y)}, columns=['a','b','c','d'], index=['x','y','z'])сработает?
Энди Хейден
@xApple, вероятно, лучше всего для вас создать список dicts (или список), а затем просто перейти к конструктору, будет намного эффективнее
Джефф
71

Мой подход был таким, но я не могу гарантировать, что это самое быстрое решение.

df = pd.DataFrame(columns=["firstname", "lastname"])
df = df.append({
     "firstname": "John",
     "lastname":  "Johny"
      }, ignore_index=True)
течь
источник
4
Это отлично сработало для меня, и мне нравится тот факт, что вы явно appendпередаете данные в фрейм данных.
Джонни Брукс
1
Обратите внимание, что этот ответ требует, чтобы к каждой строке было добавлено имя столбца. То же самое и для принятого ответа.
pashute
Это тоже работает, если вы заранее не знаете количество строк.
irene
34

Это более простая версия

import pandas as pd
df = pd.DataFrame(columns=('col1', 'col2', 'col3'))
for i in range(5):
   df.loc[i] = ['<some value for first>','<some value for second>','<some value for third>']`
Satheesh
источник
4
просто хочу спросить, эффективны ли этот процессор и память?
czxttkl
1
как мне узнать последнюю строку df, чтобы каждый раз добавлять ее к последней строке?
pashute
25

Если ваши входные строки представляют собой списки, а не словари, то следующее простое решение:

import pandas as pd
list_of_lists = []
list_of_lists.append([1,2,3])
list_of_lists.append([4,5,6])

pd.DataFrame(list_of_lists, columns=['A', 'B', 'C'])
#    A  B  C
# 0  1  2  3
# 1  4  5  6
stackoverflowuser2010
источник
но что мне делать, если у меня мультииндекс? df1 = pd.DataFrame (list_of_lists, columns ['A', 'B', 'C'], index = ['A', 'B']) не работает. Неправильная форма. Так как?
pashute