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

时间:2017-09-22 12:48:41

标签: python pandas dataframe

我最近迁移到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中执行此操作的任何想法?

4 个答案:

答案 0 :(得分:4)

如果您正在使用python和处理数字,那么通常会使用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

答案 1 :(得分:3)

使用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

答案 2 :(得分:2)

我觉得这自然是一个groupby概念,理想情况下会使用基于groupby的方法,尽管基于班次的方法肯定没有任何问题(请参阅下面的简要讨论以获取更多信息):

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

nth(0)选择每个groupby的第一行,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会导致对排序顺序的答案不变,而使用shift方法将取决于排序顺序(根据具体情况,其中任何一种都可能是首选)。 / p>

答案 3 :(得分:1)

对不起,晚会。原始要求的变化。如何使用python程序捕获sas第一个点记录?以下示例基于https://pandas.pydata.org/pandas-docs/stable/getting_started/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

最后是python程序,请注意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 )

很抱歉,不同的问题和答案,希望对您有用。