Python 使用值、索引和合并复制最后一行

Python 使用值、索引和合并复制最后一行,python,pandas,numpy,Python,Pandas,Numpy,我有这个数据框: ID X1 X2 X3 Y A 9 2 3 10 A 3 5 5 0 A 3 3 4 0 A 6 3 6 20 A 6 7 4 0 A 2 4 9 0 A 1 7 8 0 B 6 9 5 0 B 3 3 7 10 B 6 7 8 20 B 5 2 7 0 B 2 9

我有这个数据框:

ID  X1  X2  X3   Y
 A   9   2   3  10
 A   3   5   5   0
 A   3   3   4   0
 A   6   3   6  20
 A   6   7   4   0
 A   2   4   9   0
 A   1   7   8   0
 B   6   9   5   0
 B   3   3   7  10
 B   6   7   8  20
 B   5   2   7   0
 B   2   9   3  10
 B   7   2   7   0
 B   9   2   6   0
 C   2   9   4  30
 C   5   1   5  40
 C   8   3   2   0
 C   2   1   9  40
 C   3   9   8  30
 C   7   9   6  20
 D   8   2   6  10
 D   3   1   8   0
 D   4   8   9  20
 D   7   3   2  10
 F   2   8   8   0
 F   7   4   8   0
第1步:

首先,为每个ID复制最后一行,
groupby('ID')
),跳过
Y
列中的
0
值。

然后,索引行(通过
df['index']=df.index

在步骤1之后,
df
应该如下所示:

 index ID  X1  X2  X3   Y
     1  A   9   2   3  10
     2  A   3   5   5   0
     3  A   3   3   4   0
     4  A   6   3   6  20
     5  A   6   7   4   0
     6  A   2   4   9   0
     7  A   1   7   8   0
     8  A   6   3   6  20
     9  B   6   9   5   0
    10  B   3   3   7  10
    11  B   6   7   8  20
    12  B   5   2   7   0
    13  B   2   9   3  10
    14  B   7   2   7   0
    15  B   9   2   6   0
    16  B   2   9   3  10
    17  C   2   9   4  30
    18  C   5   1   5  40
    19  C   8   3   2   0
    20  C   2   1   9  40
    21  C   3   9   8  30
    22  C   7   9   6  20
    23  C   7   9   6  20
    24  D   8   2   6  10
    25  D   3   1   8   0
    26  D   4   8   9  20
    27  D   7   3   2  10
    28  D   7   3   2  10
    29  F   2   8   8   0
    30  F   7   4   8   0 
 index ID  X1  X2  X3  X4   Y
     1  A   9   2   3   1  10
     4  A   6   3   6   1  20
     8  A   6   3   6   1  20
    10  B   3   3   7   1  10
    11  B   6   7   8   1  20
    13  B   2   9   3   1  10
    16  B   2   9   3   1  10
    17  C   2   9   4   1  30
    18  C   5   1   5   1  40
    20  C   2   1   9   1  40
    21  C   3   9   8   1  30
    22  C   7   9   6   1  20
    23  C   7   9   6   1  20
    24  D   8   2   6   1  10
    26  D   4   8   9   1  20
    27  D   7   3   2   1  10
    28  D   7   3   2   1  10
第2步:

首先,排除
Y
列中
0
的人(按
df2=df[df['Y']!=0]

然后创建
X4
列(无论分配哪个值。在本例中,我通过
df2['X4']=np.one(len(df2))
X4
中的所有行分配
1

  • 注意:事实上,在这一步中,我通过计算创建了一些其他变量,但这对于示例来说并不重要
在步骤2之后,
df2
应该如下所示:

 index ID  X1  X2  X3   Y
     1  A   9   2   3  10
     2  A   3   5   5   0
     3  A   3   3   4   0
     4  A   6   3   6  20
     5  A   6   7   4   0
     6  A   2   4   9   0
     7  A   1   7   8   0
     8  A   6   3   6  20
     9  B   6   9   5   0
    10  B   3   3   7  10
    11  B   6   7   8  20
    12  B   5   2   7   0
    13  B   2   9   3  10
    14  B   7   2   7   0
    15  B   9   2   6   0
    16  B   2   9   3  10
    17  C   2   9   4  30
    18  C   5   1   5  40
    19  C   8   3   2   0
    20  C   2   1   9  40
    21  C   3   9   8  30
    22  C   7   9   6  20
    23  C   7   9   6  20
    24  D   8   2   6  10
    25  D   3   1   8   0
    26  D   4   8   9  20
    27  D   7   3   2  10
    28  D   7   3   2  10
    29  F   2   8   8   0
    30  F   7   4   8   0 
 index ID  X1  X2  X3  X4   Y
     1  A   9   2   3   1  10
     4  A   6   3   6   1  20
     8  A   6   3   6   1  20
    10  B   3   3   7   1  10
    11  B   6   7   8   1  20
    13  B   2   9   3   1  10
    16  B   2   9   3   1  10
    17  C   2   9   4   1  30
    18  C   5   1   5   1  40
    20  C   2   1   9   1  40
    21  C   3   9   8   1  30
    22  C   7   9   6   1  20
    23  C   7   9   6   1  20
    24  D   8   2   6   1  10
    26  D   4   8   9   1  20
    27  D   7   3   2   1  10
    28  D   7   3   2   1  10
第三步:

首先,在
索引上将
df
df2
合并(通过
df=df.merge(df2,on='index',how='left')

然后,排除前面添加的最后一行,用于每个ID

最终结果(
df
):


请按照步骤进行操作,这很重要,因为我会执行此处未显示的其他操作。的想法是通过
Y
删除
0
值,然后通过
ID
复制到
df1
,但为了正确排序,使用索引值映射
+0.5
,因此,在正确的顺序之后:

#df['index'] = df.index + 1

idx = df.drop_duplicates('ID', keep='last')['ID']
idx = pd.Series(idx.index + .5, idx)
#print (idx)

df1 = df[df['Y'].ne(0)].drop_duplicates('ID', keep='last')
df1.index = df1['ID'].map(idx)
df = pd.concat([df, df1]).sort_index().reset_index(drop=True)
df['index'] = np.arange(1, len(df)+1)

df2 = df[df['Y'] != 0].copy()
df2['X4'] = 1
#print (df2)
df = df.merge(df2[['index','X4']], on = 'index', how = 'left')
如果
X2
不是
NaN
,则最后通过
ID
过滤掉最后重复的值:

df = df[df['ID'].duplicated(keep='last') | df['X4'].isna()]
print (df)
   ID  X1  X2  X3   Y  index   X4
0   A   9   2   3  10      1  1.0
1   A   3   5   5   0      2  NaN
2   A   3   3   4   0      3  NaN
3   A   6   3   6  20      4  1.0
4   A   6   7   4   0      5  NaN
5   A   2   4   9   0      6  NaN
6   A   1   7   8   0      7  NaN
8   B   6   9   5   0      9  NaN
9   B   3   3   7  10     10  1.0
10  B   6   7   8  20     11  1.0
11  B   5   2   7   0     12  NaN
12  B   2   9   3  10     13  1.0
13  B   7   2   7   0     14  NaN
14  B   9   2   6   0     15  NaN
16  C   2   9   4  30     17  1.0
17  C   5   1   5  40     18  1.0
18  C   8   3   2   0     19  NaN
19  C   2   1   9  40     20  1.0
20  C   3   9   8  30     21  1.0
21  C   7   9   6  20     22  1.0
23  D   8   2   6  10     24  1.0
24  D   3   1   8   0     25  NaN
25  D   4   8   9  20     26  1.0
26  D   7   3   2  10     27  1.0
28  F   2   8   8   0     29  NaN
29  F   7   4   8   0     30  NaN
编辑:

最后一行的另一个想法是:

def f(x):
    y = x[x['Y'].ne(0)].tail(1)
    return x.append(y)

df = df.groupby('ID').apply(f)
print (df)
      ID  X1  X2  X3   Y
ID                      
A  0   A   9   2   3  10
   1   A   3   5   5   0
   2   A   3   3   4   0
   3   A   6   3   6  20
   4   A   6   7   4   0
   5   A   2   4   9   0
   6   A   1   7   8   0
   3   A   6   3   6  20
B  7   B   6   9   5   0
   8   B   3   3   7  10
   9   B   6   7   8  20
   10  B   5   2   7   0
   11  B   2   9   3  10
   12  B   7   2   7   0
   13  B   9   2   6   0
   11  B   2   9   3  10
C  14  C   2   9   4  30
   15  C   5   1   5  40
   16  C   8   3   2   0
   17  C   2   1   9  40
   18  C   3   9   8  30
   19  C   7   9   6  20
   19  C   7   9   6  20
D  20  D   8   2   6  10
   21  D   3   1   8   0
   22  D   4   8   9  20
   23  D   7   3   2  10
   23  D   7   3   2  10
F  24  F   2   8   8   0
   25  F   7   4   8   0

嗨,谢谢。除了
0
值之外,是否还有其他方法可以复制每个ID的最后一行?(除了<代码>删除重复项<代码>…)这很好。但是,如何将它们作为每个ID的最后一行插入?@qwerty-hmmm,
df1.index=df1['ID']。无法使用map(idx)
?如果否,原因是什么?@qwerty-已为新的附加解决方案编辑了答案。@qwerty-您可以测试吗<代码>df.groupby('ID')。应用(如果x.Y.iat[-1]!=0,则lambda x:x.iloc[:-1])