#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
Во-первых, мы можем импортировать некоторые пакеты, которые могут быть полезны
import pandas as pd
import datetime
Допустим, теперь у меня есть фрейм данных, в котором есть столбец даты, имени и возраста.
df1 = pd.DataFrame({'date': ['10-04-2020', '04-07-2019', '12-05-2015' ], 'name': ['john', 'tim', 'sam'], 'age':[20, 22, 27]})
Теперь предположим, что у меня есть другой фрейм данных с несколькими случайными столбцами
df2 = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6]})
Вопрос:
Как я могу взять значение возраста df1
, отфильтрованное по дате (можно выбрать это значение) df2
, и заполнить этим значением целый новый столбец? В идеале этот метод должен быть обобщен для любого количества строк в фрейме данных.
Пробовал
Ниже приведено то, что я пробовал (на аналогичном примере), но по какой-то причине это, похоже, не работает (он просто показывает значения nan в большинстве записей столбца, за исключением нескольких, которые, кажется, заполняются случайным образом).
y = datetime.datetime(2015, 5, 12)
df2['new'] = df1[(df1['date'] == y)].age
Ожидаемый результат
Поскольку я отфильтровал выше на основе возраста sams (дата соответствует строке с именем sams) Я бы хотел, чтобы новый столбец был добавлен в df2 с указанием его возраста, как и все записи (в данном случае 27 повторяется 3 раза).
df2 = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6], 'new': [27, 27, 27]})
Комментарии:
1. пожалуйста, опубликуйте ожидаемый результат
2. Конечно, только что добавлено
3. что делать, если есть два
sam
, один с возрастом27
, а другой с25
?4. Ах, извините, я только что упомянул имя сэма, чтобы упростить задачу (похоже, у него сложные вещи). Не обращайте на это внимания, думайте об этом как о фильтрации по дате, которая всегда будет уникальной, а затем выбирайте возраст на основе этого. Поэтому в идеале, если я изменю указанную дату, он должен выбрать возрастной номер (из
df1
), а затем заполнить новый столбец (вdf2
) этим значением
Ответ №1:
Попробуйте:
y = datetime.datetime(2015, 5, 12).strftime('%d-%m-%Y')
df2.loc[:, 'new'] = df1.loc[df1['date'] == y, "age"].item()
# Output
a b new
0 1 4 27
1 2 5 27
2 3 6 27
Комментарии:
1. Не уверен, работает ли это, похоже, выдает ошибку.
2. Это потому, что даты в df1
strings
, тогда как y — этоdatetime64
объект. Повторите попытку с кодом в моем обновленном ответе.3. Вы случайно не знаете, почему это работает, а мой оригинальный метод — нет? Например, если я изменил y на строку, а затем попытался использовать
df2['new'] = df1[(df1['date'] == y)].age
, что-то не так с этим?4. Ваш
date
столбец неdatetime
имеет типа, скорее это простоstring
тип. Поэтому, когда вы сравниваетеstring
сdatetime
объектом, вы получаете ошибку @nishcs. Но этот ответ выполняет толькоstring
string
сравнение и, следовательно, он работает.5. но, скажем, я превращаю свое datetime в строку, используя
y = datetime.datetime(2015, 5, 12).strftime('%d-%m-%Y')
then, является ли моя командаdf2['new'] = df1[(df1['date'] == y)].age
по-прежнему допустимым решением?
Ответ №2:
Вы хотели бы изменить формат y на Str и попробовать метод df.loc
y = datetime.datetime(2015, 5, 12)
y=y.strftime('%d-%m-%Y')
df2['new']=int(df1.loc[df1['date']==y,'age'].values)
df2
Ответ №3:
Преобразовать date
столбец df1 в datetime
тип
df1['date'] = pd.to_datetime(df1.date, format='%d-%m-%Y')
Отфильтруйте фрейм данных и получите возраст
req_date = '2015-05-12'
age_for_date = df1.query('date == @req_date').age.iloc[0]
ПРИМЕЧАНИЕ: предполагается, что для каждой даты существует только один возраст (как объяснено OP в комментариях)
Создайте новый столбец
df2 = df2.assign(new=age_for_date)
Вывод
a b new
0 1 4 27
1 2 5 27
2 3 6 27
Комментарии:
1. Является ли метод assign лучшим для создания новых столбцов по сравнению с приравниванием?
2. Хороший вопрос @nishcs. Я использую assign из-за его структурной простоты и гибкости при назначении нескольких столбцов с использованием словаря. С точки зрения эффективности по времени assign немного медленнее, поскольку он выполняет копирование после назначения. Для создания нескольких столбцов и удобства чтения я предпочитаю его простому назначению.