Python 无法计算列中唯一值的频率

Python 无法计算列中唯一值的频率,python,pandas,numpy,dataframe,import-from-excel,Python,Pandas,Numpy,Dataframe,Import From Excel,我正在做一个项目,要求我计算一个学生在不同学科的课堂上出现的次数和缺席的次数,并计算他的出勤率。我有他的出勤记录如下 Attend Date Subject 96 Present 09-04-2020 AM-II 69 Present 16-04-2020 AM-II 61 Present 20-04-2020 AM-II 49 Present 22-04-2020 AM-II 45 Present 23-04-2020 AM-II ... ... ... .

我正在做一个项目,要求我计算一个学生在不同学科的课堂上出现的次数和缺席的次数,并计算他的出勤率。我有他的出勤记录如下

    Attend  Date    Subject
96  Present 09-04-2020  AM-II
69  Present 16-04-2020  AM-II
61  Present 20-04-2020  AM-II
49  Present 22-04-2020  AM-II
45  Present 23-04-2020  AM-II
... ... ... ...
14  Present 12-04-2020  LMS
13  Absent  18-04-2020  LMS
11  Absent  19-04-2020  LMS
10  Present 25-04-2020  LMS
9   Present 26-04-2020  LMS
我正在使用python的pandas库来计算每个独特主题的“存在”和“缺席”出现的次数,但我无法做到这一点。这就是我正在做的

data=pd.read_csv("data1.csv") 
  
#sorting data frame by Team and then By names 
data.sort_values(["Subject", "Date"], axis=0, 
                 ascending=True, inplace=True) 
p = 0
a = 0
total = 0
attpercent = {}
data.set_index(["Subject"], inplace = True, 
                            append = True, drop = False)
temp = ""
data = data.infer_objects()
for Subject, Attend in data.iterrows()
    if(temp == ""):
        temp = Subject
        if Attend == "Present":
                p = p + 1
        else:
            a = a + 1
    else:
        if(temp == Subject):
            if Attend == "Present":
                p = p + 1
            else:
                a = a + 1
        else:
            total = a + p
            attpercent[temp] = (p * 100) / total
            a = 0
            p = 0
            temp = Subject 
            if Attend == "Present":
                p = p + 1
            else:
                a = a + 1
                
print(attpercent)
它显示了一个错误:

 TypeError                                 Traceback (most recent call last)
<ipython-input-65-9d7243427e5f> in <module>
     18 data = data.infer_objects()
     19 for Subject, Attend in data.iterrows():
---> 20     Attend = str(Attend)
     21     if(temp == ""):
     22         temp = Subject

TypeError: 'Series' object is not callable
TypeError回溯(最近一次调用)
在里面
18数据=数据。推断对象()
19对于受试者,参加data.iterrows():
--->20出席=str(出席)
21如果(温度=“”):
22温度=受试者
TypeError:“Series”对象不可调用

我是第一次使用熊猫,所以我对它知之甚少。我尝试使用
expert\u objects
astypes()
转换列的类型,但仍然得到相同的错误。请提供帮助。

您应该尽量避免for循环和迭代,并熟悉
pandas
方法,如
.groupby
.pivot\u table
取消堆栈
。对于此特定问题,您可以将
.groupby
.size
一起使用,然后使用
.unstack
将行移动到列,并以良好的格式获取数据,以准备计算出勤率

df = df.groupby(['Subject','Attend']).size().reset_index() \
       .set_index(['Subject', 'Attend']) \
       .unstack(1).fillna(0).astype(int)
df.columns = df.columns.droplevel(0)
df['Attendance'] = df['Present'] / ( df['Present'] + df['Absent'])
df
输出:

Attend  Absent  Present Attendance
Subject         
AM-II   0       5       1.0
LMS     2       3       0.6
更详细的解释

在相关列上进行
.groupby
size
后,使用
.set_index(['Subject',attention'])
计算出现次数,我将在索引上设置这两列,为下一步做准备。接下来,我将
atteent
移动到标题,以将此数据集放入一个良好的矩阵格式,如和Excel Pivot表。使用
.unstack(1)
,我将使用我刚刚设置的第二个索引列(记住python从
0
开始,所以
1
现在将第二个索引列作为我的标题,基本上以一种非常方便的方式将数据帧从行重塑为列。如果我使用
.unstack(0)
,它会将
主题
移动到标题,这样就不会以我们想要的方式可视化数据

最后,
df.columns=df.columns.droplevel(0)
从多索引中删除一个级别,使其看起来更干净,然后
出勤率的计算非常简单,它将出席人数除以总人数,得到每个主题的出勤率


比如说,完整的数据包含了另一个学生专栏。根据第一个例子,你可能会尝试从这里找出如何做到这一点,但这是你可以做的

输入:

    Attend  Date       Subject  Student
96  Present 09-04-2020  AM-II   Kathy
69  Present 16-04-2020  AM-II   John
61  Present 20-04-2020  AM-II   John
49  Present 22-04-2020  AM-II   John
45  Present 23-04-2020  AM-II   Kathy
14  Present 12-04-2020  LMS     Kathy
13  Absent  18-04-2020  LMS     Kathy
11  Absent  19-04-2020  LMS     John
10  Present 25-04-2020  LMS     Kathy
9   Present 26-04-2020  LMS     John
代码:

代码几乎相同。您只需使用
.groupby
.set_index()
和增加
.unstack
fom
1
2
,因为
出席
列现在是
指定的第三个
索引
。然后,将
drop\u level(1)
更改为
drop\u level(0)
,因为索引上有两列

最后,如果您想要一个没有多索引的干净数据集,只需执行
df=df.reset_index()
作为返回的最后一步:

Attend  Student Subject Absent  Present Attendance
0       John    AM-II   0       3       1.000000
1       John    LMS     1       1       0.500000
2       Kathy   AM-II   0       2       1.000000
3       Kathy   LMS     1       2       0.666667

iterrow()不返回列它将返回行,您应该使用
作为索引,数据中的行。iterrow()
t您可以通过
row[attribute]
row['Subject'访问列值
谢谢您的解释性回答。但是我不明白为什么不显示“日期”列?当我试图将其放入groupby()中时,df[“出席”]不会显示正确答案,因为它会显示每天的出席率%。如果我想在特定日期后计算出席率%,我该怎么做?@YashSethia,“date”不包括在groupby中,因此它不包括在最终结果中,但您是正确的,您无论如何都不想按日期分组。要筛选af请指定一个具体的日期做'df.loc[df['date']>'09-04-2020'。groupby'..您可以用任何日期替换'09-04-2020'。希望这有帮助。请投票并接受,如果有帮助。我试着写了这个'data=data.loc[data[“date”>“01-05-2020”]。groupby(['Subject',Attend']).size().重置索引()\.设置索引(['Subject','Attend'])\.unstack(1).fillna(0).astype(int)'但它不起作用。我仍然得到所有dates@YashSerthia在groupby之前,请尝试使用data['Date']=pd.to_datetime(data['Date'],dayfirst=True)…然后尝试使用…data=data.loc[data[“Date”]>“2020-05-01”]如果出现错误,请将其发布。我使用了data[“Date”]=pd.to_datetime(data['Date'],dayfirst=True)data=data.loc[data['Date']>“01-05-2020”]但什么都没有发生。整个数据的输出仍然是。
Attend  Student Subject Absent  Present Attendance
0       John    AM-II   0       3       1.000000
1       John    LMS     1       1       0.500000
2       Kathy   AM-II   0       2       1.000000
3       Kathy   LMS     1       2       0.666667