使用 Python 复制 SAS 的第一个和最后一个功能



我最近迁移到python作为我的主要工具,我希望能够复制第一个。&最后的。在SAS中发现的功能。SAS代码如下;

data data.out;
   set data.in;
   if first.ID then flag = 1;
   if last.ID then flag = 1;
run;

输出将如下;

ID     flag
AAAA   1
AAAA   0
AAAA   0
AAAA   1
BBBB   1
BBBB   0
BBBB   0
BBBB   1
CCCC   1
CCCC   0
CCCC   1

关于如何在Python中执行此操作的任何想法?

如果您使用的是python和Crunching数字,通常会使用pandas

进行此类操作
pip install pandas

假设您有一个CSV文件,则可以使用pd.read_csv加载数据。我不会对您的输入做出假设,因此请查看文档。加载数据框后,您可以继续。

import pandas
df = pd.read_csv('file.csv')
df
      ID
0   AAAA
1   AAAA
2   AAAA
3   AAAA
4   BBBB
5   BBBB
6   BBBB
7   BBBB
8   CCCC
9   CCCC
10  CCCC
df['flag'] = ((df.ID != df.ID.shift()) | (df.ID != df.ID.shift(-1))).astype(int)
df
      ID  flag
0   AAAA     1
1   AAAA     0
2   AAAA     0
3   AAAA     1
4   BBBB     1
5   BBBB     0
6   BBBB     0
7   BBBB     1
8   CCCC     1
9   CCCC     0
10  CCCC     1

您也可以使用np.where(Brad Solomon的建议)来执行此操作:

df['flag'] = np.where((df.ID != df.ID.shift()) 
                  | (df.ID != df.ID.shift(-1)), 1, 0)
df
      ID  flag
0   AAAA     1
1   AAAA     0
2   AAAA     0
3   AAAA     1
4   BBBB     1
5   BBBB     0
6   BBBB     0
7   BBBB     1
8   CCCC     1
9   CCCC     0
10  CCCC     1

使用pandas:

import pandas as pd
import numpy as np
df = pd.DataFrame(['AAAA', 'AAAA', 'AAAA', 'AAAA', 
                   'BBBB', 'BBBB', 'BBBB', 'BBBB', 'CCCC', 'CCCC', 'CCCC',],
                  columns=['ID'])
def firstlast(a):
    # For each character grouping set, create a 1d array of 0s padded
    #     with 1s, equal to length of the group.
    a = np.zeros(len(a)-2)
    a = np.pad(a, (1,1), 'constant', constant_values=(1,1))
    return a
df['flag'] = (s.groupby(s).apply(firstlast).apply(pd.Series).stack()
                  .astype(int).values)
print(df)
      ID  flag
0   AAAA     1
1   AAAA     0
2   AAAA     0
3   AAAA     1
4   BBBB     1
5   BBBB     0
6   BBBB     0
7   BBBB     1
8   CCCC     1
9   CCCC     0
10  CCCC     1

在逻辑上从 @cᴏʟᴅsᴘᴇᴇᴅ中窃取一点(这比上述解决方案更聪明),但使用 numpy.where

ids = df.ID
df['flag'] = np.where((ids!=ids.shift(1)) | (ids!=ids.shift(-1)), 1, 0)
print(df)
      ID  flag
0   AAAA     1
1   AAAA     0
2   AAAA     0
3   AAAA     1
4   BBBB     1
5   BBBB     0
6   BBBB     0
7   BBBB     1
8   CCCC     1
9   CCCC     0
10  CCCC     1

我觉得这自然是一个群体概念,理想情况下会使用基于组的方法,尽管基于轮班的方法肯定没有错(请参阅下面对此的简短讨论有关更多):

df.loc[ df.groupby('ID',as_index=False).nth([0,-1]).index, 'flag' ] = 1

nth(0)选择每个组的第一行,而 nth(-1) nth([0,-1])选择同时选择。这将使其他行缺失,可以很容易地用fillna(0)填充。

df.flag = df.flag.fillna(0).astype(int)
      ID  flag
0   AAAA     1
1   AAAA     0
2   AAAA     0
3   AAAA     1
4   BBBB     1
5   BBBB     0
6   BBBB     0
7   BBBB     1
8   CCCC     1
9   CCCC     0
10  CCCC     1

关于@Jonclements的评论,请注意,使用GroupBy会导致对排序顺序的答案不变,而使用移位方法将取决于排序顺序(这取决于特定情况,这可能是优选的)。<<<<<<<<<</p>

对不起,聚会迟到了。变化到原始需求。如何使用Python程序捕获SAS第一点记录?下面的示例基于https://pandas.pydata.org/pandas-docs/stable/getting_started/comparison/comparison/comparison_with_sas.html

第一个SAS设置:sample_dot_last和sample_dot_first数据集是我需要生产的python!

    data sampledata;
    infile cards4;
    input ( x y ) ( 2*$8. )  z record_number;
    cards;
    A            I            10    1     
    A            I            11    2   
    A            I            11    3     
    A            J            15    4     
    B            K            9     5     
    B            K            10    6     
    B            K            10    7     
    B            L            14    8     
    C            I            7     9     
    C            I            19   10     
    C            K            3    11     
    C            K            5    12     
    ;;;;
    proc print data= sampledata;
    run;
    data sample_dot_last;
     set sampledata;
      by x y z;
      if last.y;
    run;
    proc print data= sample_dot_last;
    run;
    data sample_dot_first;
     set sampledata;
      by x y z;
      if first.y;
    run;
    proc print data= sample_dot_first;
    run;

python的第二个样本CSV:

    x,y,z,record number
    A,I,10,1
    A,I,11,2
    A,I,11,3
    A,J,15,4
    B,K,9,5
    B,K,10,6
    B,K,10,7
    B,L,14,8
    C,I,7,9
    C,I,19,10
    C,K,3,11
    C,K,5,12

最后,请注意dataframe.groupby([...]).last()或.first()产生与SAS完全相同的输出!

    import numpy as np
    import pandas as pd
    import os
    cwd= os.getcwd()
    print( "cwd={}".format( cwd ))
    df1= pd.read_csv( 'sampledata.csv')
    print( df1 )
    df2= df1.groupby( [ 'x', 'y' ]).last()
    print( df2 )
    df3= df1.groupby( [ 'x', 'y' ]).first()
    print( df3 )

抱歉不同的问题和回答,希望它有用。

最新更新