У меня есть следующий индексированный DataFrame с именованными столбцами и строками, не являющимися непрерывными числами:
a b c d
2 0.671399 0.101208 -0.181532 0.241273
3 0.446172 -0.243316 0.051767 1.577318
5 0.614758 0.075793 -0.451460 -0.012493
Я хочу добавить новый столбец, 'e'
, к существующему кадру данных и не хочу ничего менять в кадре данных (т.е. новый столбец всегда имеет ту же длину, что и кадр данных).
0 -0.335485
1 -1.166658
2 -0.385571
dtype: float64
Я пробовал разные варианты join
, append
, merge
, но не получил желаемого результата, максимум только ошибки. Как я могу добавить столбец e
в вышеприведенный пример?
Для создания серии используйте исходные индексы df1:
df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
Правка 2015
Некоторые сообщали о получении предупреждения SettingWithCopyWarning
при использовании этого кода.
Однако код по-прежнему отлично работает с текущей версией pandas 0.16.1.
>>> sLength = len(df1['a'])
>>> df1
a b c d
6 -0.269221 -0.026476 0.997517 1.294385
8 0.917438 0.847941 0.034235 -0.448948
>>> df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
a b c d e
6 -0.269221 -0.026476 0.997517 1.294385 1.757167
8 0.917438 0.847941 0.034235 -0.448948 2.228131
>>> p.version.short_version
'0.16.1'
Предупреждение SettingWithCopyWarning
призвано сообщить о возможном некорректном присвоении копии Dataframe. Оно не обязательно говорит, что вы сделали это неправильно (это может вызвать ложные срабатывания), но начиная с версии 0.13.0 оно дает вам знать, что есть более адекватные методы для той же цели. Затем, если вы получите предупреждение, просто следуйте его рекомендациям: Попробуйте вместо этого использовать .loc[row_index,col_indexer] = value.
>>> df1.loc[:,'f'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
a b c d e f
6 -0.269221 -0.026476 0.997517 1.294385 1.757167 -0.050927
8 0.917438 0.847941 0.034235 -0.448948 2.228131 0.006109
>>>
На самом деле, это более эффективный метод, как описано в документации pandas.
Редактирование 2017
Как указано в комментариях и @Alexander, в настоящее время лучшим методом добавления значений серии в качестве нового столбца DataFrame может быть использование assign
:
df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)
Вот простой способ добавления нового столбца: df['e'] = e
.
Я хочу добавить новый столбец, 'e', к существующему кадру данных и ничего не менять в кадре данных. (Серия всегда имеет ту же длину, что и кадр данных).
Я предполагаю, что значения индексов в e
совпадают со значениями в df1
.
Проще всего создать новый столбец с именем e
и присвоить ему значения из вашей серии e
:
df['e'] = e.values
assign (Pandas 0.16.0+).
Начиная с Pandas 0.16.0, вы также можете использовать assign
, который присваивает новые столбцы DataFrame и возвращает новый объект (копию) со всеми исходными столбцами в дополнение к новым.
df1 = df1.assign(e=e.values)
Согласно этому примеру (который также включает исходный код функции assign
), вы также можете включить более одного столбца:
df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df.assign(mean_a=df.a.mean(), mean_b=df.b.mean())
a b mean_a mean_b
0 1 3 1.5 3.5
1 2 4 1.5 3.5
В контексте вашего примера:
np.random.seed(0)
df1 = pd.DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'])
mask = df1.applymap(lambda x: x <-0.7)
df1 = df1[-mask.any(axis=1)]
sLength = len(df1['a'])
e = pd.Series(np.random.randn(sLength))
>>> df1
a b c d
0 1.764052 0.400157 0.978738 2.240893
2 -0.103219 0.410599 0.144044 1.454274
3 0.761038 0.121675 0.443863 0.333674
7 1.532779 1.469359 0.154947 0.378163
9 1.230291 1.202380 -0.387327 -0.302303
>>> e
0 -1.048553
1 -1.420018
2 -1.706270
3 1.950775
4 -0.509652
dtype: float64
df1 = df1.assign(e=e.values)
>>> df1
a b c d e
0 1.764052 0.400157 0.978738 2.240893 -1.048553
2 -0.103219 0.410599 0.144044 1.454274 -1.420018
3 0.761038 0.121675 0.443863 0.333674 -1.706270
7 1.532779 1.469359 0.154947 0.378163 1.950775
9 1.230291 1.202380 -0.387327 -0.302303 -0.509652
Описание этой новой функции, когда она была впервые представлена, можно найти здесь.
Похоже, что в последние панды версии путь заключается в использовании df.assign:
df1 = df1.назначить(е=НП.случайные.randn(sLength))
Это не'т произвести SettingWithCopyWarning
.
Выполнение этого напрямую через NumPy будет наиболее эффективным:
df1['e'] = np.random.randn(sLength)
Обратите внимание, что мое первоначальное (очень старое) предложение было использовать map
(что намного медленнее):
df1['e'] = df1['a'].map(lambda x: np.random.random())
В панды фрейма данных осуществляется как упорядоченное дикт столбцов.
Это означает, что __метод getitem__
[]
не может быть использован только для получения определенного столбца, но __setitem класса__
[] =
может быть использована, чтобы назначить новую колонку.
Например, этой таблицы данных может быть добавлен столбец, чтобы она просто с помощью []
аксессу
size name color
0 big rose red
1 small violet blue
2 small tulip red
3 small harebell blue
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
Обратите внимание, что это работает, даже если индекс таблицы данных выключена.
df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
Однако, если у вас есть ПД.Серии и попытаться присвоить его Таблицы данных, где индексы отключены, вы будете работать в беду. См. пример:
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Это потому, что ПД.Серия
по умолчанию имеет индекс пронумерованы от 0 до n. И панд[] =` метод нах чтобы быть "умные"
Когда вы используете [] =
метод панд спокойно выполнять внешнее соединение или космического слияния, используя указательный левой руки таблицы данных и указательным правой руки. серия `ДФ['колонки'] = серии
Это быстро вызывает когнитивный диссонанс, поскольку []=
метод пытается сделать много разных вещей в зависимости от входных данных, и результат не может быть предсказано, если вы точно знаю как панды работ. Поэтому я бы посоветовал против []=
в базах кода, но при просмотре данных в записной книжке, это хорошо.
Если у вас есть ПД.Серия` и хотите, чтобы он назначается сверху вниз, или если вы маркировка производственного кода, и вы не уверены в индекс, стоит того, чтобы избежать такого рода проблемы.
Вы могли бы потупив в ПД.Серии на НП.ndarray
или список
, это будет делать трюк.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values
или
df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))
Но это не очень ясно.
Какой кодер может прийти и сказать: ""Эй, это выглядит излишним, я'МР просто оптимизировать это&;.
Установка индекс ДП.Серия
для индекса ДФ
явный.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)
Или более реалистично, вы, вероятно, есть `ПД.Серии уже доступен.
protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index
3 no
2 no
1 no
0 yes
Теперь можно назначать
df['protected'] = protected_series
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
Поскольку индекс диссонанс является проблемой, если вы чувствуете, что индекс таблицы данных должен не диктуют вещи, вы можете просто удалить индекс, это должно быть быстрее, но это не очень чистый, так как ваша функция наверное делает две вещи.
df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
В то время как ДФ.назначить сделать это более ясным, что вы делаете, это на самом деле имеет все те же проблемы, как и выше
[]=`
df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Просто смотреть с ДФ.назначить, что ваша колонка называется не "я". Это приведет к ошибкам. Это делает `ДФ.назначить вонючие, так как есть такие артефакты в функции.
df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'
Вы можете сказать: "Ну, я'Лл просто не использовать "я", потом". Но кто знает, как эта функция изменения в будущем для поддержки новых аргументов. Может быть, ваше имя столбца будет аргумент в новое обновление панды, вызывая проблемы с обновлением.
Если вы хотите, чтобы весь новый столбец в исходной базовой стоимости (например, нет
), вы можете сделать это: `df1['е'] = Нет
Это на самом деле было бы назначить на "объект" и типа ячейки. Так что поздно вы'вновь свободной, чтобы поставить сложные типы данных, такие как список, в отдельные клетки.
У меня SettingWithCopyWarning страшный`, и это было'т исправить с помощью синтаксиса Мот. Мои таблицы данных был создан read_sql из источника ODBC. Используя предложение lowtech выше, следующие работал для меня:
df.insert(len(df.columns), 'e', pd.Series(np.random.randn(sLength), index=df.index))
Это хорошо работало, чтобы вставить столбец в конец. Я не'т знаю, если это является наиболее эффективным, но я не'т, как предупреждение. Я думаю, что есть лучшее решение, но я могу'т найти его, и я думаю, что это зависит от некоторых аспектов индекса. Примечание. Что это только один раз и выдаст сообщение об ошибке при попытке перезаписи и существующего столбца. Примечание как указано выше, и от 0.16.0 назначить лучшее решение. См http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign документация Хорошо работает для типа потока данных, где вы Дон'т перезаписать свои промежуточные значения.
list_of_e
, который имеет соответствующие данные. ДФ['е'] = list_of_e
Если столбец, который вы пытаетесь добавить переменную серии, то просто :
df["new_columns_name"]=series_variable_name #this will do it for you
Это хорошо работает, даже если вы заменяете существующий столбец.просто введите new_columns_name совпадает со столбцом, который вы хотите заменить.Это будет просто перезаписать существующие данные с новыми данными серии.
Надежный:
df.loc[:, 'NewCol'] = 'New_Val'
Пример:
df = pd.DataFrame(data=np.random.randn(20, 4), columns=['A', 'B', 'C', 'D'])
df
A B C D
0 -0.761269 0.477348 1.170614 0.752714
1 1.217250 -0.930860 -0.769324 -0.408642
2 -0.619679 -1.227659 -0.259135 1.700294
3 -0.147354 0.778707 0.479145 2.284143
4 -0.529529 0.000571 0.913779 1.395894
5 2.592400 0.637253 1.441096 -0.631468
6 0.757178 0.240012 -0.553820 1.177202
7 -0.986128 -1.313843 0.788589 -0.707836
8 0.606985 -2.232903 -1.358107 -2.855494
9 -0.692013 0.671866 1.179466 -1.180351
10 -1.093707 -0.530600 0.182926 -1.296494
11 -0.143273 -0.503199 -1.328728 0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832 0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15 0.955298 -1.430019 1.434071 -0.088215
16 -0.227946 0.047462 0.373573 -0.111675
17 1.627912 0.043611 1.743403 -0.012714
18 0.693458 0.144327 0.329500 -0.655045
19 0.104425 0.037412 0.450598 -0.923387
df.drop([3, 5, 8, 10, 18], inplace=True)
df
A B C D
0 -0.761269 0.477348 1.170614 0.752714
1 1.217250 -0.930860 -0.769324 -0.408642
2 -0.619679 -1.227659 -0.259135 1.700294
4 -0.529529 0.000571 0.913779 1.395894
6 0.757178 0.240012 -0.553820 1.177202
7 -0.986128 -1.313843 0.788589 -0.707836
9 -0.692013 0.671866 1.179466 -1.180351
11 -0.143273 -0.503199 -1.328728 0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832 0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15 0.955298 -1.430019 1.434071 -0.088215
16 -0.227946 0.047462 0.373573 -0.111675
17 1.627912 0.043611 1.743403 -0.012714
19 0.104425 0.037412 0.450598 -0.923387
df.loc[:, 'NewCol'] = 0
df
A B C D NewCol
0 -0.761269 0.477348 1.170614 0.752714 0
1 1.217250 -0.930860 -0.769324 -0.408642 0
2 -0.619679 -1.227659 -0.259135 1.700294 0
4 -0.529529 0.000571 0.913779 1.395894 0
6 0.757178 0.240012 -0.553820 1.177202 0
7 -0.986128 -1.313843 0.788589 -0.707836 0
9 -0.692013 0.671866 1.179466 -1.180351 0
11 -0.143273 -0.503199 -1.328728 0.610552 0
12 -0.923110 -1.365890 -1.366202 -1.185999 0
13 -2.026832 0.273593 -0.440426 -0.627423 0
14 -0.054503 -0.788866 -0.228088 -0.404783 0
15 0.955298 -1.430019 1.434071 -0.088215 0
16 -0.227946 0.047462 0.373573 -0.111675 0
17 1.627912 0.043611 1.743403 -0.012714 0
19 0.104425 0.037412 0.450598 -0.923387 0
Если фрейм данных и объектно серии один и тот же индекс, панды.функция concat
также работает здесь:
import pandas as pd
df
# a b c d
#0 0.671399 0.101208 -0.181532 0.241273
#1 0.446172 -0.243316 0.051767 1.577318
#2 0.614758 0.075793 -0.451460 -0.012493
e = pd.Series([-0.335485, -1.166658, -0.385571])
e
#0 -0.335485
#1 -1.166658
#2 -0.385571
#dtype: float64
# here we need to give the series object a name which converts to the new column name
# in the result
df = pd.concat([df, e.rename("e")], axis=1)
df
# a b c d e
#0 0.671399 0.101208 -0.181532 0.241273 -0.335485
#1 0.446172 -0.243316 0.051767 1.577318 -1.166658
#2 0.614758 0.075793 -0.451460 -0.012493 -0.385571
В случае, если они Дон'т иметь один и тот же индекс:
e.index = df.index
df = pd.concat([df, e.rename("e")], axis=1)
Одна вещь, чтобы отметить, что если вы делаете
df1['e'] = Series(np.random.randn(sLength), index=df1.index)
это позволит эффективно стать слева присоединиться на df1.индекс. Так что если вы хотите иметь внешний присоединяйтесь эффект, моем видимо несовершенное решение-создать таблицу данных со значениями индекса, охватывающего вселенную ваших данных, а затем использовать приведенный выше код. Например,
data = pd.DataFrame(index=all_possible_values)
df1['e'] = Series(np.random.randn(sLength), index=df1.index)
Перед назначением нового столбца, если у вас есть индексированных данных, вам нужно для сортировки индекса. По крайней мере, в моем случае мне пришлось:
data.set_index(['index_column'], inplace=True)
"if index is unsorted, assignment of a new column will fail"
data.sort_index(inplace = True)
data.loc['index_value1', 'column_y'] = np.random.randn(data.loc['index_value1', 'column_x'].shape[0])
Позвольте мне просто добавить, что, как и для hum3, .Лок
ничего'т решить SettingWithCopyWarning
и мне пришлось прибегнуть к ДФ.вставка(). В моем случае ложноположительный был создан на "фейк" в цепи индексации
дикт['а']['е'], где
'е'- новая рубрика, и дикт['Это']
- это таблицы данных, поступающих из словаря.
Также обратите внимание, что если вы знаете, что вы делаете, вы можете переключиться предупреждения, используя `ПД.варианты.режим.chained_assignment = нет и чем использовать другие решения проблемы.
Я ищу общий способ добавления столбца `и NumPy.Нэн в таблицу данных без получения SettingWithCopyWarning тупой``.
Из следующего:
включает
массив Нанс в он-лайнЯ придумал это:
col = 'column_name'
df = df.assign(**{col:numpy.full(len(df), numpy.nan)})
чтобы вставить новый столбец в данном месте (0 <= Лок <= количество столбцов) во фрейме данных, просто использовать таблицы данных.вставка:
DataFrame.insert(loc, column, value)
Поэтому, если вы хотите, чтобы добавить столбец е в конце фрейм данных называется ДТ, вы можете использовать:
e = [-0.335485, -1.166658, -0.385571]
DataFrame.insert(loc=len(df.columns), column='e', value=e)
значение может быть серия, целое число (в этом случае все клетки наполняются этом одно значение), или массив-как структура
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html
Для полноты картины - еще одно решение, используя таблицы данных.функция eval() метод:
Сведения:
In [44]: e
Out[44]:
0 1.225506
1 -1.033944
2 -0.498953
3 -0.373332
4 0.615030
5 -0.622436
dtype: float64
In [45]: df1
Out[45]:
a b c d
0 -0.634222 -0.103264 0.745069 0.801288
4 0.782387 -0.090279 0.757662 -0.602408
5 -0.117456 2.124496 1.057301 0.765466
7 0.767532 0.104304 -0.586850 1.051297
8 -0.103272 0.958334 1.163092 1.182315
9 -0.616254 0.296678 -0.112027 0.679112
Решение:
In [46]: df1.eval("e = @e.values", inplace=True)
In [47]: df1
Out[47]:
a b c d e
0 -0.634222 -0.103264 0.745069 0.801288 1.225506
4 0.782387 -0.090279 0.757662 -0.602408 -1.033944
5 -0.117456 2.124496 1.057301 0.765466 -0.498953
7 0.767532 0.104304 -0.586850 1.051297 -0.373332
8 -0.103272 0.958334 1.163092 1.182315 0.615030
9 -0.616254 0.296678 -0.112027 0.679112 -0.622436