[英]Pandas - how to add multiple conditional columns to dataframe?
所以我想做的是根据条件创建几个计算并将它们添加到数据帧中。 下面是一些代码作为示例:
data = pd.DataFrame({'Project': ['Project 1', 'Project 2', ' Project 3', 'Project 4', 'Project 5', 'Project 6', 'Project 7', 'Project 8', 'Project 9', 'Project 10'],
'Date': ['10/1/2020', '10/1/2020', '11/1/2020', '12/1/2020', '12/1/2020', '12/1/2020', '2/1/2021', '2/1/2021', '3/1/2021', '4/1/2021'],
'Team': ['Team 1', 'Team 2', 'Team 3', 'Team 2', 'Team 2', 'Team 2', 'Team 1', 'Team 1', 'Team 1', 'Team 1'],
'Timely': ['Yes', 'No', 'No', 'Yes', 'Yes', 'No', 'No', 'Yes', 'Yes', 'Yes']})
df1=data.groupby('Team')['Timely'].apply(lambda x: (x=='Yes').sum()).reset_index(name='Yes Count')
df1
运行此代码将为我提供一个表格,其中显示每个团队及时 = Yes 的项目数。 假设我想在表格中添加第二列以显示总计数,其中及时 = 否,第三列和第四列显示每个团队的百分比是和否。 我该怎么做?
在我看来,你只想要一个交叉表。 使用pd.crosstab
计算比使用groupby/apply
方法更直接。 虽然pd.crosstab
不是最有效的方法,但它工作得很好。
第一个片段为我们提供了每个团队的“是”和“否”计数。 我们还得到一个“总计”列,它是“是”+“否”的总和:
xtab = pd.crosstab(data["Team"], data["Timely"], margins=True, margins_name="Total")
print(xtab)
Timely No Yes Total
Team
Team 1 1 4 5
Team 2 2 2 4
Team 3 1 0 1
Total 4 6 10
现在让我们通过将它们除以我们的“总计”列来计算“否”和“是”的百分比细分:
norm_xtab = xtab[["No", "Yes"]].div(xtab["Total"], axis=0)
print(norm_xtab)
Timely No Yes
Team
Team 1 0.2 0.8
Team 2 0.5 0.5
Team 3 1.0 0.0
Total 0.4 0.6
然后我们可以将这两个数据帧与pd.concat
函数水平组合。 我们还可以为每个“子数据帧”命名,例如数据帧的一个块将仅用于计数数据,另一块将用于标准化/基于百分比的数据:
out = pd.concat([xtab, norm_xtab], keys=["count", "percent"], axis=1)
out = out.rename(columns={"No": "untimely", "Yes": "timely"}, level=1)
print(out)
count percent
Timely untimely timely Total untimely timely
Team
Team 1 1 4 5 0.2 0.8
Team 2 2 2 4 0.5 0.5
Team 3 1 0 1 1.0 0.0
Total 4 6 10 0.4 0.6
连接的结果是一个以多索引作为列的 DataFrame。 如果您不熟悉 pd.MultiIndex,您可以使用此代码段将您的结果展平为您可能更熟悉的内容:
out.columns = ["{}_{}".format(*colname) for colname in out.columns]
print(out)
count_untimely count_timely count_Total percent_untimely percent_timely
Team
Team 1 1 4 5 0.2 0.8
Team 2 2 2 4 0.5 0.5
Team 3 1 0 1 1.0 0.0
Total 4 6 10 0.4 0.6
要更改下面评论中的列名称,您只需再运行一次rename
:
out = out.rename(columns=lambda colname: colname.replace("count_", ""))
print(out)
untimely timely Total percent_untimely percent_timely
Team
Team 1 1 4 5 0.2 0.8
Team 2 2 2 4 0.5 0.5
Team 3 1 0 1 1.0 0.0
Total 4 6 10 0.4 0.6
要将小数转换为整数百分比,您需要乘以 100,然后四舍五入到 0 位小数或使用字符串格式来修剪尾随小数(我将向您展示如何执行这两个操作),并添加另一个字符串格式让“%”出现。
percentages = (out
.filter(like="percent") # select columns that contain the string "percent"
.mul(100) # Multiply everything by 100
.round(0) # If you don't want to perform any rounding, get rid of this line
.applymap("{:.0f}%".format)) # Apply string formatting to trim the decimal.
print(percentages)
percent_untimely percent_timely
Team
Team 1 20% 80%
Team 2 50% 50%
Team 3 100% 0%
Total 40% 60%
如果您希望这些值反映在我们的out
数据框中:
out.loc[:, percentages.columns] = percentages
print(out)
untimely timely Total percent_untimely percent_timely
Team
Team 1 1 4 5 20% 80%
Team 2 2 2 4 50% 50%
Team 3 1 0 1 100% 0%
Total 4 6 10 40% 60%
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.