Як додати окремий предмет до серії Pandas


77

Як додати один елемент до серіалізованої серії панд? Я знаю, що це не найефективніший спосіб пам’яті, але мені все одно потрібно це зробити.

Щось разом:

>> x = Series()
>> N = 4
>> for i in xrange(N):
>>     x.some_appending_function(i**2)    
>> print x

0 | 0
1 | 1
2 | 4
3 | 9

також, як я можу додати один рядок до pandas DataFrame?


Пов’язане: Створення порожнього Pandas DataFrame, а потім заповнення? - TLDR створює список, а потім перетворює на серію в кінці.
cs95

Відповіді:


46

Як додати один елемент. Це не дуже ефективно, але слідує тому, про що ви просите:

x = p.Series()
N = 4
for i in xrange(N):
   x = x.set_value(i, i**2)

виробляє x:

0    0
1    1
2    4
3    9

Очевидно, що є кращі способи створити цю серію лише одним кадром.

Для другого запитання перевірте відповідь та посилання на запитання SO, додайте один рядок у pandas.DataFrame .


Яку версію панд ви використовуєте? Я використовую 0.14.1 і отримую таку помилку: IndexError: index 0 is out of bounds for axis 0 with size 0
Бен,

@Ben, не впевнений, відповідь старше 2 років. Я тестував з 0.15.0, і він працює ідеально. Ви виконуєте той самий точний код ?
Хоакін

Так, я просто вставив код прямо в нову консоль. Дивно, здається, зараз це працює!
Бен

1
У python> 3 вам це не потрібно, x = x.set_value(i, i**2)тому що x.set_value()вносить зміни xбезпосередньо.
jeongmin.cha

16
Так, set_value () застаріло. Використовуйте x.at[i] = i**2або x.iat[i] = i**2.
Вольфганг Кюхн

39

TLDR: не додавати елементи до серії один за одним, краще розширити за допомогою упорядкованої колекції

Я думаю, що питання у його нинішньому вигляді є дещо хитрим. І прийнята відповідь дійсно відповідає на питання. Але чим більше я використовую панд, тим більше розумію, що погано додавати елементи до Серії по одному. Спробую пояснити, чому для панд-початківців.

Ви можете подумати, що додавання даних до даної Серії може дозволити Вам повторно використати деякі ресурси, але насправді Серія - це просто контейнер, який зберігає відношення між індексом та масивом значень. Кожен - це масив numpy.arry під капотом, а індекс незмінний. Коли ви додаєте до Серії елемент із міткою, якої немає в індексі, створюється новий індекс розміром n + 1 та масив значень нових значень того самого розміру. Це означає, що коли ви додаєте елементи по одному, ви створюєте ще два масиви розміром n + 1 на кожному кроці.

До речі, ви не можете додати новий елемент за позицією (ви отримаєте IndexError), і мітка в індексі не повинна бути унікальною, тобто коли ви присвоюєте значення міткою, ви присвоюєте значення усім наявні елементи з міткою, і новий рядок у цьому випадку не додається. Це може призвести до незначних помилок.

Мораль історії полягає в тому, що ви не повинні додавати дані один за іншим, вам краще поширити їх із замовленою колекцією. Проблема в тому, що ви не можете продовжити серію на місці. Ось чому краще впорядкувати свій код так, щоб вам не потрібно було оновлювати певний екземпляр серії за посиланням.

Якщо ви створюєте мітки самостійно, і вони збільшуються, найпростіший спосіб - додати нові елементи до словника, а потім створити нову серію зі словника (вона сортує ключі) і додати серію до старої. Якщо ключі не збільшуються, вам потрібно буде створити два окремих списки для нових міток та нових значень.

Нижче наведено кілька зразків коду:

In [1]: import pandas as pd
In [2]: import numpy as np

In [3]: s = pd.Series(np.arange(4)**2, index=np.arange(4))

In [4]: s
Out[4]:
0    0
1    1
2    4
3    9
dtype: int64

In [6]: id(s.index), id(s.values)
Out[6]: (4470549648, 4470593296)

Коли ми оновлюємо існуючий елемент, індекс та масив значень залишаються незмінними (якщо ти не змінюєш тип значення)

In [7]: s[2] = 14  

In [8]: id(s.index), id(s.values)
Out[8]: (4470549648, 4470593296)

Але коли ви додаєте новий елемент, генерується новий індекс та новий масив значень:

In [9]: s[4] = 16

In [10]: s
Out[10]:
0     0
1     1
2    14
3     9
4    16
dtype: int64

In [11]: id(s.index), id(s.values)
Out[11]: (4470548560, 4470595056)

Тобто якщо ви збираєтеся додати кілька предметів, зібрати їх у словник, створити Серію, додати її до старої та зберегти результат:

In [13]: new_items = {item: item**2 for item in range(5, 7)}

In [14]: s2 = pd.Series(new_items)

In [15]: s2  # keys are guaranteed to be sorted!
Out[15]:
5    25
6    36
dtype: int64

In [16]: s = s.append(s2); s
Out[16]:
0     0
1     1
2    14
3     9
4    16
5    25
6    36
dtype: int64

25

Якщо у вас є індекс і значення. Тоді ви можете додати до серії як:

obj = Series([4,7,-5,3])
obj.index=['a', 'b', 'c', 'd']

obj['e'] = 181

це додасть нове значення Серії (в кінці Серії).


2
Чудова відповідь, коротка і пряма.
Briford Wylie

1
Це найкраща відповідь
boardtc

12

Ви можете використовувати функцію додавання, щоб додати до неї інший елемент. Тільки складіть серію нового елемента, перш ніж додавати його:

test = test.append(pd.Series(200, index=[101]))

3
Я вважаю, додаток повертає нову серію (а не робить це на місці), тому ви хочетеtest = test.append(pd.Series(200, index=[101]))
А.Ван

1
@ A.Wan так, мав би це зробити більш чітким. Дякую!
fixxxer

7

Додавши до відповіді Джокіна, наступна форма може бути трохи чистішою (принаймні приємнішою для читання):

x = p.Series()
N = 4
for i in xrange(N):
   x[i] = i**2

що дало б однаковий результат

також, трохи менш ортодоксальний, але якщо ви хочете просто додати один елемент до кінця:

x=p.Series()
value_to_append=5
x[len(x)]=value_to_append

друга частина коду не працює в python 3
М. Чавоші,

3

Оскільки рішення @ joaqin застаріло, оскільки set_valueметод буде вилучено в майбутньому випуску панд, я б згадав про інший варіант додати один елемент до серії панд, використовуючи .at[]accessor.

>>> import pandas as pd
>>> x = pd.Series()
>>> N = 4
>>> for i in range(N):
...     x.at[i] = i**2

Це дає той самий результат.

>>> print(x)
0    0
1    1
2    4
3    9


0

Ось ще одна думка n щодо додавання декількох елементів в один рядок без зміни назви серії. Однак це може бути не настільки ефективним, як інша відповідь.

>>> df = pd.Series(np.random.random(5), name='random')
>>> df

0    0.363885
1    0.402623
2    0.450449
3    0.172917
4    0.983481
Name: random, dtype: float64


>>> df.to_frame().T.assign(a=3, b=2, c=5).squeeze()

0    0.363885
1    0.402623
2    0.450449
3    0.172917
4    0.983481
a    3.000000
b    2.000000
c    5.000000
Name: random, dtype: float64
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.