熊猫-如何向数据框添加多个条件列?

时间:2020-09-28 22:09:23

标签: python pandas dataframe

所以我想做的是根据条件创建几个计算并将它们添加到数据框中。这是一些代码作为示例:

codesign --display --verbose <path-to-app>

运行此代码将为我提供一个表格,该表格显示每个团队的及时=是的项目数。假设我想在表格中添加第二列以显示及时=否的总计数,并在第三列和第四列中显示每个团队的是和否百分比。我该怎么办?

1 个答案:

答案 0 :(得分:1)

在我看来,就像您只想要一个交叉表一样。使用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

连接的结果是一个以multiindex作为列的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%