Python 如何使用,带条件的groupby,然后在DataFrame中使用cumcount

Python 如何使用,带条件的groupby,然后在DataFrame中使用cumcount,python,pandas,Python,Pandas,我有以下数据集: df = pd.DataFrame( [ ['John', 3, Yes], ['John', 4, No], ['Alex', 2, No], ['Alex', 6, No], ['John', 7, No], ['John', 2, Yes], ['Alex', 1, Yes] ], columns = ['Name', 'TestType','T

我有以下数据集:

df = pd.DataFrame(
    [
        ['John', 3, Yes],
        ['John', 4, No],
        ['Alex', 2, No],
        ['Alex', 6, No],
        ['John', 7, No],
        ['John', 2, Yes],
        ['Alex', 1, Yes]
    ], columns = ['Name', 'TestType','Test'])
给我:

print(df):

Name        TestType          Test
John         3                 Yes
John         4                 No
Alex         2                 No
Alex         6                 No
John         7                 No
John         2                 Yes 
Alex         1                 Yes 
该表是按时间顺序排列的,因此我试图实现的是
TestType
小于5的测试的最新计数,以及
TestType
小于5的人员所进行的测试的百分比计数

我希望输出为:

print (df):
Name        TestType          Test       TestsUnder5      TestPCunder5
John         3                 Yes            1              100%
John         4                 No             2              50%
Alex         2                 No             1              0%
Alex         6                 Yes            1              0% 
John         7                 No             2              50%
John         2                 Yes            3              67%
Alex         1                 Yes            2              50%

我想我需要使用
groupby
cumsum
,但不确定如何指定条件,然后执行计算。任何帮助都将不胜感激

快到了!您可以将数学运算符应用于布尔级数,这会将它们强制为整数0或1。对于TestsUnder5,看起来这可能会起作用:

df['TestsUnder5']=(df.TestType<5).groupby(df.Name).apply(np.cumsum)
类似地,对于百分比,您可以使用二进制并集来获得5以下的测试:

df['TestPCunder5']=(
(
((df.Test=='Yes')&(df.TestType<5))
.groupby(df.Name).apply(np.cumsum)
)/df['TestsUnder5']
)
您的示例结果似乎是格式为“{:.0%}”的字符串。如果这就是您要查找的内容,则可以将此列强制为字符串:

df['TestPCunder5']=df['TestPCunder5'].apply(“{.0%}.”格式)

快到了!您可以将数学运算符应用于布尔级数,这会将它们强制为整数0或1。对于TestsUnder5,看起来这可能会起作用:

df['TestsUnder5']=(df.TestType<5).groupby(df.Name).apply(np.cumsum)
类似地,对于百分比,您可以使用二进制并集来获得5以下的测试:

df['TestPCunder5']=(
(
((df.Test=='Yes')&(df.TestType<5))
.groupby(df.Name).apply(np.cumsum)
)/df['TestsUnder5']
)
您的示例结果似乎是格式为“{:.0%}”的字符串。如果这就是您要查找的内容,则可以将此列强制为字符串:

df['TestPCunder5']=df['TestPCunder5'].apply(“{.0%}.”格式)
这是我的方法:

newdf = (df.assign(TestUnder5=df.TestType.lt(5),
          TestTaken=df.TestType.lt(5) & df.Test.eq('Yes')
         )
   .groupby('Name')
   [['TestUnder5','TestTaken']]
   .cumsum()
)

# update original dataframe
df['TestUnder5'] = newdf['TestUnder5']
df['TestPCunder5'] = newdf['TestTaken']/newdf['TestUnder5']
输出:

   Name  TestType Test  TestUnder5  TestPCunder5
0  John         3  Yes         1.0      1.000000
1  John         4   No         2.0      0.500000
2  Alex         2   No         1.0      0.000000
3  Alex         6   No         1.0      0.000000
4  John         7   No         2.0      0.500000
5  John         2  Yes         3.0      0.666667
6  Alex         1  Yes         2.0      0.500000
这是我的方法:

newdf = (df.assign(TestUnder5=df.TestType.lt(5),
          TestTaken=df.TestType.lt(5) & df.Test.eq('Yes')
         )
   .groupby('Name')
   [['TestUnder5','TestTaken']]
   .cumsum()
)

# update original dataframe
df['TestUnder5'] = newdf['TestUnder5']
df['TestPCunder5'] = newdf['TestTaken']/newdf['TestUnder5']
输出:

   Name  TestType Test  TestUnder5  TestPCunder5
0  John         3  Yes         1.0      1.000000
1  John         4   No         2.0      0.500000
2  Alex         2   No         1.0      0.000000
3  Alex         6   No         1.0      0.000000
4  John         7   No         2.0      0.500000
5  John         2  Yes         3.0      0.666667
6  Alex         1  Yes         2.0      0.500000

这太棒了。非常感谢@Michale Delgado!这对我来说很有意义,所以我应该能够将这些应用到其他专栏中。这太棒了。非常感谢@Michale Delgado!这对我来说是有意义的,所以应该能够将这些应用到其他专栏。非常感谢你的回复!我最终选择了Michale的解决方案,但这看起来同样不错!非常感谢您的回复!我最终选择了Michale的解决方案,但这看起来同样不错!