簡體   English   中英

在python中運行countifs的更快方法

[英]faster way to run countifs in python

我之前曾問過有關如何在多個數據幀中使用python進行計數的問題,就像您可以在Excel中的單獨工作表上進行計數一樣。 有人給我一個非常有創意的答案:

使用多個條件和多個數據框的python pandas countifs

謝謝@AlexG的支持-我嘗試了一下,它的效果非常好:

import pandas as pd
import numpy as np
import matplotlib as plt

#import the data
students = pd.read_csv("Student Detail stump.csv")
exams = pd.read_csv("Exam Detail stump.csv")

#get data parameters
student_info = students[['Student Number', 'Enrollment Date', 'Detail Date']].values

#prepare an empty list to hold the results
N_exams_passed = []

#count records in data set according to parameters
for s_id, s_enroll, s_qual in student_info:
N_exams_passed.append(len(exams[(exams['Student Number']==s_id) &
                         (exams['Exam Grade Date']>=s_enroll) &
                         (exams['Exam Grade Date']<=s_qual) &
                         (exams['Exam Grade']>=70)])
                      )

#add the results to the original data set
students['Exams Passed'] = N_exams_passed

但是,它僅在小型數據集上有效地工作。 當我用十萬行的數據運行數據時,它甚至不可能一overnight而就。 它似乎不是很pythonic。

您可以在幾秒鍾內完成此操作的SQL方法是使用相關子查詢,如下所示:

SELECT
   s.*,
   (SELECT COUNT(e.[Exam Grade]) 
 FROM
     exams AS e 
 WHERE
    e.[Exam Grade] >= 65 
    AND e.[Student Number] = s.[Student Number] 
    AND e.[Exam Grade Date] >= s.[Enrollment Date] 
    AND e.[Exam Grade Date] <= s.[Detail Date]) 
    AS ExamsPassed
FROM 
    students AS s;

如何以熊貓或其他pythonic方式重現此類相關子查詢?

以下是數據幀:

 #Students
 Student Number Enroll Date Detail Date
 1              1/1/2016    2/1/2016
 1              1/1/2016    3/1/2016
 2              2/1/2016    3/1/2016
 3              3/1/2016    4/1/2016

 #Exams
 Student Number Exam Date   Exam Grade
 1              1/1/2016    50
 1              1/15/2016   80
 1              1/28/2016   90
 1              2/5/2016    100
 1              3/5/2016    80
 1              4/5/2016    40
 2              2/2/2016    85
 2              2/3/2016    10
 2              2/4/2016    100

最終數據幀應如下所示,最后是“通過的考試”:

 #FinalResult
 Student Number Enroll Date Detail Date Passed Exams
 1              1/1/2016    2/1/2016    2
 1              1/1/2016    3/1/2016    3
 2              2/1/2016    3/1/2016    2
 3              3/1/2016    4/1/2016    0

如果我正確理解了數據幀的結構,建議合並兩個數據幀,然后使用numpy.where對合並后的數據執行任務。

import numpy as np

exams = exams.merge(students, on='Student Number', how='left')
exams['Passed'] = np.where(
    (exams['Exam Grade Date'] >= exams['Enrollment Date']) &
    (exams['Exam Grade Date'] <= exams['Detail Date']) &
    (exams['Grade'] >= 70),
    1, 0)

students = students.merge(
    exams.groupby(['Student Number', 'Detail Date'])['Passed'].sum().reset_index(),
    left_on=['Student Number', 'Detail Date'],
    right_on=['Student Number', 'Detail Date'],
    how='left')
students['Passed'] = students['Passed'].fillna(0).astype('int')

注意:您需要確保將日期列正確地存儲為日期時間(可以使用pandas.to_datetime進行此操作)。

numpy.where創建一個新數組,如果滿足指定條件,則值是一種方式(上例中為1 ),如果不滿足,則為另一種方式( 0 )。

exams.groupby(['Student Number', 'Detail Date'])['Passed'].sum()生成一個序列,其中索引為Student NumberDetail Date ,並且值是與通過的考試相對應的計數該Student NumberDetail Date組合。 reset_index()使它成為一個數據reset_index()以進行合並。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM