Вставить строку в фреймворк pandas


112

У меня есть фреймворк:

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

   A  B  C
0  5  6  7
1  7  8  9

[2 rows x 3 columns]

и мне нужно добавить первую строку [2, 3, 4], чтобы получить:

   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Я пробовал append()и concat()функционирует, но не могу найти правильный способ это сделать.

Как добавить / вставить серию в фрейм данных?


6
обратите внимание, что лучше использовать s1.valuesвместо того, чтобы list(s1)создавать совершенно новый список, используя list(s1).
acushner

7
Я не понимаю, почему все так любят панд, когда то, что должно быть настолько простым, становится такой головной болью и так медленно.
Мэтт Кокрейн,

Ответы:


145

Просто назначьте строку определенному индексу, используя loc:

 df.loc[-1] = [2, 3, 4]  # adding a row
 df.index = df.index + 1  # shifting index
 df = df.sort_index()  # sorting by index

И вы получите по желанию:

    A  B  C
 0  2  3  4
 1  5  6  7
 2  7  8  9

См. В документации Pandas Индексирование: Настройка с увеличением .


2
Если вы не хотите устанавливать с увеличением, но вставляете в фрейм данных, посмотрите stackoverflow.com/questions/15888648/…
FooBar

6
Альтернатива смещения индекса: df.sort (). reset_index (drop = True)
Мелун

2
df.sort устарел, используйте df.sort_index ()
GBGOLC

1
@Piotr - это отлично работает, но что произойдет, если вы захотите скопировать строку из фрейма данных, например df.loc[-1] = df.iloc[[0]], и вставить ее? Фрейм идет с добавленным столбцом индекса с ошибкой ValueError: cannot set a row with mismatched columns (см. Stackoverflow.com/questions/47340571/… )
Growler

5
Я думаю df.loc[-1] = [2, 3, 4] # adding a row, это немного вводит в заблуждение, так как -1это не последняя строка / элемент, как для массивов Python.
flow2k

27

Не знаю, как вы звонили, concat()но он должен работать, если оба объекта одного типа. Может быть, проблема в том, что вам нужно передать второй вектор в фрейм данных? Используя df, который вы определили, для меня работает следующее:

df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])

Лучший ответ ^ :)
Cam.Davidson.Pilon

23

Один из способов добиться этого -

>>> pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C']).append(df, ignore_index=True)
Out[330]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Как правило, проще всего добавлять фреймы данных, а не серии. В вашем случае, поскольку вы хотите, чтобы новая строка была «наверху» (с начальным идентификатором), а функции нет pd.prepend(), я сначала создаю новый фрейм данных, а затем добавляю ваш старый.

ignore_indexбудет игнорировать старый текущий индекс в вашем фрейме данных и гарантировать, что первая строка действительно начинается с индекса, 1а не перезапускается с индекса 0.

Типичный отказ от ответственности: Cetero censeo ... добавление строк - довольно неэффективная операция. Если вы заботитесь о производительности и можете каким-то образом обеспечить сначала создание фрейма данных с правильным (более длинным) индексом, а затем просто вставку дополнительной строки в фрейм данных, вы обязательно должны это сделать. Видеть:

>>> index = np.array([0, 1, 2])
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[0:1] = [list(s1), list(s2)]
>>> df2
Out[336]: 
     A    B    C
0    5    6    7
1    7    8    9
2  NaN  NaN  NaN
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[1:] = [list(s1), list(s2)]

Пока что у нас есть то, что у вас было df:

>>> df2
Out[339]: 
     A    B    C
0  NaN  NaN  NaN
1    5    6    7
2    7    8    9

Но теперь вы можете легко вставить строку следующим образом. Поскольку пространство было выделено заранее, это более эффективно.

>>> df2.loc[0] = np.array([2, 3, 4])
>>> df2
Out[341]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Это хорошее временное решение, я пытался вставить серию в фрейм данных. На данный момент для меня этого достаточно.
Meloun

Мне больше всего нравится последний вариант. Это действительно соответствует тому, чем я действительно хочу заниматься. Спасибо @FooBar!
Jade Cacho

13

Я собрал короткую функцию, которая дает немного больше гибкости при вставке строки:

def insert_row(idx, df, df_insert):
    dfA = df.iloc[:idx, ]
    dfB = df.iloc[idx:, ]

    df = dfA.append(df_insert).append(dfB).reset_index(drop = True)

    return df

который может быть сокращен до:

def insert_row(idx, df, df_insert):
    return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop = True)

Тогда вы можете использовать что-то вроде:

df = insert_row(2, df, df_new)

где 2- позиция индекса, в которую dfвы хотите вставить df_new.


7

Мы можем использовать numpy.insert. Это дает преимущество гибкости. Вам нужно только указать индекс, в который вы хотите вставить.

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

pd.DataFrame(np.insert(df.values, 0, values=[2, 3, 4], axis=0))

    0   1   2
0   2   3   4
1   5   6   7
2   7   8   9

В np.insert(df.values, 0, values=[2, 3, 4], axis=0)самом деле, 0 указывает функции место / индекс, в котором вы хотите разместить новые значения.


6

это может показаться слишком простым, но невероятно, что простая функция вставки новой строки не встроена. Я много читал о добавлении нового df к оригиналу, но мне интересно, будет ли это быстрее.

df.loc[0] = [row1data, blah...]
i = len(df) + 1
df.loc[i] = [row2data, blah...]

Вы имели в виду «добавление нового df» или просто «добавление новой строки», как показывает ваш код?
smci

извините, мое предложение было неясным. Я читал решения других людей, которые объединяют / добавляют совершенно новый фрейм данных только с одной строкой. но в моем решении это всего лишь одна строка в существующем фрейме данных, нет необходимости в создании дополнительного фрейма данных
Аарон Мелгар,

6

Ниже будет лучший способ вставить строку в фрейм данных pandas без сортировки и сброса индекса:

import pandas as pd

df = pd.DataFrame(columns=['a','b','c'])

def insert(df, row):
    insert_loc = df.index.max()

    if pd.isna(insert_loc):
        df.loc[0] = row
    else:
        df.loc[insert_loc + 1] = row

insert(df,[2,3,4])
insert(df,[8,9,0])
print(df)

почему вы сказали, что это лучший способ?
Юк

тогда было бы неплохо предоставить доказательства в поддержку этого утверждения, вы рассчитали время?
Юк

1
вы можете использовать pd.isna, чтобы избежать импорта numpy
kato2

2

Добавить строку в панд довольно просто DataFrame :

  1. Создайте обычный словарь Python с теми же именами столбцов, что и ваш Dataframe ;

  2. Используйте pandas.append()метод и передайте имя своего словаря, где.append() - метод экземпляров DataFrame;

  3. Добавьте ignore_index=Trueсразу после названия словаря.


Это, наверное, самый предпочтительный вариант (примерно 2020 год).
Дэвид Голембиовски

1

concat()кажется немного быстрее, чем вставка и переиндексация последней строки. На случай, если кто-то поинтересовался скоростью двух топовых подходов:

In [x]: %%timeit
     ...: df = pd.DataFrame(columns=['a','b'])
     ...: for i in range(10000):
     ...:     df.loc[-1] = [1,2]
     ...:     df.index = df.index + 1
     ...:     df = df.sort_index()

17,1 с ± 705 мс на цикл (среднее ± стандартное отклонение из 7 прогонов, по 1 циклу в каждом)

In [y]: %%timeit
     ...: df = pd.DataFrame(columns=['a', 'b'])
     ...: for i in range(10000):
     ...:     df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df])

6,53 с ± 127 мс на цикл (среднее ± стандартное отклонение из 7 прогонов, по 1 циклу)


0

Вы можете просто добавить строку в конец DataFrame, а затем настроить индекс.

Например:

df = df.append(pd.DataFrame([[2,3,4]],columns=df.columns),ignore_index=True)
df.index = (df.index + 1) % len(df)
df = df.sort_index()

Или используйте concatкак:

df = pd.concat([pd.DataFrame([[1,2,3,4,5,6]],columns=df.columns),df],ignore_index=True)

-1

Самый простой способ добавить строку во фрейм данных pandas:

DataFrame.loc[ location of insertion ]= list( )

Пример :

DF.loc[ 9 ] = [ ´Pepe , 33, ´Japan ]

NB: длина вашего списка должна соответствовать длине фрейма данных.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.