#pandas #dataframe
Вопрос:
Я новичок в python, поэтому, пожалуйста, помогите мне.
У меня есть фрейм данных, который имеет
df
id status emailaddress ownername Key
a pending a.gmail.com as 1
a pending a.gmail.com as 2
a submitted a.gmail.com as 3
a submitted a.gmail.com as 4
b pending b.gmail.com bs 1
b pending b.gmail.com bs 2
b pending b.gmail.com bs 3
b pending b.gmail.com bs 4
b pending b.gmail.com bs 1
c submitted c.gmail.com bs 1
c submitted c.gmail.com bs 3
c submitted c.gmail.com bs 4
Я хочу рассчитать количество ключевых столбцов на основе статуса для каждого идентификатора.
Также, если статус какой-либо один статус = ожидание, то общий статус этого пользователя будет ожидаться в сводной таблице.
Общий ключ = количество (Ключ) , где статус(в ожидании)
CompletedKey = количество (Ключ) , где статус(отправлен)
Ожидаемый df_summary
id status emailaddress ownername TotalKey CompletedKey RemainingKey
a pending a.gmail.com as 4 2 2
b pending b.gmail.com bs 5 0 4
c submitted c.gmail.com cs 3 3 0
Мой код
dfResponse = df.groupby(['id','ownername','status','emailaddress'])['Key'].count().reset_index(name="TotalKey")
Ответ №1:
Используется agg
для вычисления счетчиков и слияния с исходным кадром данных. Чтобы сохранить правильный статус, создайте упорядоченный категориальный тип dtype, чтобы pending
при сортировке значений статус отображался первым.
>>> df.astype({'status': pd.CategoricalDtype(['pending', 'submitted'], ordered=True)})
.merge(df.groupby('id')
.agg(TotalKey=('Key', 'count'),
CompletedKey=('status', lambda x: sum(x == 'submitted')),
RemainingKey=('status', lambda x: sum(x == 'pending'))),
on='id')
.sort_values('status')
.drop_duplicates('id')
.drop(columns='Key')
id status emailaddress ownername TotalKey CompletedKey RemainingKey
0 a pending a.gmail.com as 4 2 2
4 b pending b.gmail.com bs 5 0 5
9 c submitted c.gmail.com bs 3 3 0
Ответ №2:
Используйте assign
для создания логических столбцов для различных ключевых столбцов, которые вы хотите сделать, затем вы можете использовать sum
после groupby
. для столбца состояние сохраняйте where
ожидание и используйте first
после groupby
, чтобы получить значение ожидание, когда по крайней мере один находится в группе, а затем fillna
отсутствующее состояние по отправлено — потому что если нет, то только отправлено для этой группы.
dfResponse = (
df.assign(
TotalKey=True,
CompletedKey=lambda x: x['status'].eq('submitted'),
RemainingKey=lambda x: ~x['CompletedKey'], # assuming it is either submitted or pending
status=lambda x: x['status'].where(x['RemainingKey'])) # keep only the pending values
.groupby(['id','ownername','emailaddress']) # remove status from groupby
.agg({'status':'first', # get pending if any pending in the group
'TotalKey':sum, # sum because these columns are boolean
'CompletedKey':sum,
'RemainingKey':sum})
.fillna({'status':'submitted'}) # fill missing status when no pending
.reset_index()
)
print(dfResponse)
id ownername emailaddress status TotalKey CompletedKey RemainingKey
0 a as a.gmail.com pending 4 2 2
1 b bs b.gmail.com pending 5 0 5
2 c bs c.gmail.com submitted 3 3 0
Комментарии:
1. Вы можете упростить
assign
иagg
за однуagg
операцию, нет?2. @Corralien да, я согласен, сначала я пошел этим путем, так как не видел требований к столбцу статуса, и использование
assign
было способом сделатьgroupby.sum
это непосредственно для всех ключевых столбцов. После добавления столбца статуса он больше не является лучшим..
Ответ №3:
Вы можете объединить .groupby
(для определения количества каждой ожидающей/отправленной группы) .pivot_table
(для изменения формы/суммирования фрейма данных):
x = df.groupby(["id", "status"], as_index=False).agg(
{
"status": "first",
"emailaddress": "first",
"ownername": "first",
"Key": "count",
}
)
x = x.pivot_table(
index=["id", "emailaddress", "ownername", "status"],
columns="status",
aggfunc="sum",
)
x.columns = x.columns.map("_".join)
x = (
x.rename(
columns={"Key_pending": "RemainingKey", "Key_submitted": "CompletedKey"}
)
.fillna(0)
.astype(int)
)
x["TotalKey"] = x.sum(1)
print(x.reset_index().sort_values(["id", "status"]).drop_duplicates("id"))
С принтами:
id emailaddress ownername status RemainingKey CompletedKey TotalKey
0 a a.gmail.com as pending 2 0 2
2 b b.gmail.com bs pending 5 0 5
3 c c.gmail.com bs submitted 0 3 3
Комментарии:
1. @Ben. Готово. 🙂