计数0个值

时间:2015-06-01 21:42:49

标签: sas

here类似,我可以计算缺失观察的数量:​​

data dataset;
  input a b c;
cards;
1 2 3
0 1 0
0 0 0
7 6 .
. 3 0
0 0 .
;
run;

proc means data=dataset NMISS N;
run;

但我怎样才能计算0的观察数量?

4 个答案:

答案 0 :(得分:4)

如果您想计算0的观察数量,您需要使用proc tabulateproc freq,并进行频率计数。

如果你有很多价值而你只想要" 0 /不是0"那么format很容易做到。

data have;
  input a b c;
cards;
1 2 3
0 1 0
0 0 0
7 6 .
. 3 0
0 0 .
;
run;

proc format;
  value zerof
  0='Zero'
  .='Missing'
  other='Not Zero';
quit;

proc freq data=have;
  format _numeric_ zerof.;
  tables _numeric_/missing;
run;

这些方面的东西。显然要小心_numeric_作为所有数字变量,如果你有很多数字变量,可能会很快变得凌乱......

答案 1 :(得分:2)

我将此作为补充答案添加。它要求您拥有PROC IML

这使用矩阵操作来计算。

(ds=0) - 创建值为0 = 0

的0/1值(false / true)的矩阵

[+,] - 对所有列的行进行求和。如果我们有0/1值,那么这是每列的值= 0。

' - 运算符是转置。

|| - 合并矩阵{0} || {1} = {0 1}

然后我们只打印值。

proc iml;
use dataset;
read all var _num_ into ds[colname=names];
close dataset;
ds2 = ((ds=0)[+,])`;

n = nrow(ds);

ds2 = ds2 || repeat(n,ncol(ds),1);

cnames = {"N = 0", "Count"};
mattrib ds2 rowname=names colname=cnames;

print ds2;
quit;

答案 2 :(得分:1)

最容易使用PROC SQL。您必须使用UNION复制MEANS输出;

第一个FROM的每个部分计算每个变量的0值,UNION将它们叠加起来。

最后一部分只计算DATASET中的观察次数。

proc sql;
select n0.Variable, 
       n0.N_0 label="Number 0", 
       n.count as N
 from (
   select "A" as Variable,
          count(a) as N_0
      from dataset
      where a=0
   UNION 
   select "B" as Variable,
          count(b) as N_0
      from dataset
      where b=0
   UNION
   select "C" as Variable,
          count(c) as N_0
      from dataset
      where c=0
) as n0,
(
    select count(*) as count
    from dataset
) as n;
quit;

答案 3 :(得分:1)

你可以使用proc freq中的级别选项。

Public Class Impersonator
    Private _username As String
    Private _password As String
    Private _domainname As String

    Private _tokenHandle As New IntPtr(0)
    Private _dupeTokenHandle As New IntPtr(0)
    Private _impersonatedUser As System.Security.Principal.WindowsImpersonationContext

#Region "Constructor"
    Public Sub New(ByVal username As String, _
                   ByVal password As String)
        Dim nameparts() As String = username.Split(Convert.ToChar("\"))
        If nameparts.Length > 1 Then
            _domainname = nameparts(0)
            _username = nameparts(1)
        Else
            _username = username
        End If
        _password = password
    End Sub

    Public Sub New(ByVal username As String, _
                   ByVal password As String, _
                   ByVal domainname As String)
        _username = username
        _password = password
        _domainname = domainname
    End Sub
#End Region

#Region "Properties"
    Public ReadOnly Property username() As String
        Get
            Return _username
        End Get
    End Property

    Public ReadOnly Property domainname() As String
        Get
            Return _domainname
        End Get
    End Property

    Public ReadOnly Property currentWindowsUsername() As String
        Get
            Return System.Security.Principal.WindowsIdentity.GetCurrent().Name
        End Get
    End Property
#End Region

#Region "Impersonation"
    Public Sub BeginImpersonation()
        'Const LOGON32_PROVIDER_DEFAULT As Integer = 0
        'Const LOGON32_LOGON_INTERACTIVE As Integer = 2
        Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
        Const LOGON32_PROVIDER_WINNT50 As Integer = 3
        Const SecurityImpersonation As Integer = 2

        Dim win32ErrorNumber As Integer

        _tokenHandle = IntPtr.Zero
        _dupeTokenHandle = IntPtr.Zero

        If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle) Then
            win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Throw New ImpersonationException(win32ErrorNumber, GetErrorMessage(win32ErrorNumber), _username, _domainname)
        End If

        If Not DuplicateToken(_tokenHandle, SecurityImpersonation, _dupeTokenHandle) Then
            win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()

            CloseHandle(_tokenHandle)
            Throw New ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", _username, _domainname)
        End If

        Dim newId As New System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
        _impersonatedUser = newId.Impersonate()
    End Sub

    Public Sub EndImpersonation()
        If Not _impersonatedUser Is Nothing Then
            _impersonatedUser.Undo()
            _impersonatedUser = Nothing

            If Not System.IntPtr.op_Equality(_tokenHandle, IntPtr.Zero) Then
                CloseHandle(_tokenHandle)
            End If
            If Not System.IntPtr.op_Equality(_dupeTokenHandle, IntPtr.Zero) Then
                CloseHandle(_dupeTokenHandle)
            End If
        End If
    End Sub
#End Region

#Region "Exception Class"
    Public Class ImpersonationException
        Inherits System.Exception

        Public ReadOnly win32ErrorNumber As Integer

        Public Sub New(ByVal win32ErrorNumber As Integer, ByVal msg As String, ByVal username As String, ByVal domainname As String)
            MyBase.New(String.Format("Impersonation of {1}\{0} failed! [{2}] {3}", username, domainname, win32ErrorNumber, msg))
            Me.win32ErrorNumber = win32ErrorNumber
        End Sub
    End Class
#End Region

#Region "External Declarations and Helpers"
    Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As [String], _
            ByVal lpszDomain As [String], ByVal lpszPassword As [String], _
            ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, _
            ByRef phToken As IntPtr) As Boolean


    Private Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
                ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
                ByRef DuplicateTokenHandle As IntPtr) As Boolean


    Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean

    <System.Runtime.InteropServices.DllImport("kernel32.dll")> _
    Private Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _
          ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _
          ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer
    End Function

    Private Function GetErrorMessage(ByVal errorCode As Integer) As String
        Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
        Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
        Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000

        Dim messageSize As Integer = 255
        Dim lpMsgBuf As String = ""
        Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS

        Dim ptrlpSource As IntPtr = IntPtr.Zero
        Dim prtArguments As IntPtr = IntPtr.Zero

        Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource, errorCode, 0, lpMsgBuf, messageSize, prtArguments)
        If 0 = retVal Then
            Throw New System.Exception("Failed to format message for error code " + errorCode.ToString() + ". ")
        End If

        Return lpMsgBuf
    End Function

#End Region

End Class