python-3.x 根据特定条件复制 Dataframe 中组/ID的最后一行

cuxqih21  于 2023-04-08  发布在  Python
关注(0)|答案(2)|浏览(121)

我有下面的dataframe:

#Load the required libraries
import pandas as pd

#Create dataset
data = {'id': [1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,
               2, 2,
               3, 3, 3, 3, 3, 3,
               4, 
               5, 5, 5, 5, 5,5, 5, 5,5],
        'cycle': [1,2, 3, 4, 5,6,7,8,9,10,11,
                  1,2, 
                  1,2, 3, 4, 5,6,
                  1,
                  1,2, 3, 4, 5,6,7,8,9,],
        'Salary': [7, 7, 7,8,9,10,11,12,13,14,15,
                   4, 5,
                   8,9,10,11,12,13,
                   8,
                   7, 7,9,10,11,12,13,14,15,],
        'Children': ['No', 'Yes', 'Yes', 'Yes', 'Yes', 'No','No', 'Yes', 'Yes', 'Yes', 'No',
                     'Yes', 'No', 
                     'No','Yes', 'Yes', 'No','No', 'Yes',
                     'Yes',
                      'No',  'Yes', 'No', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'No',],
        'Days': [123, 128, 66, 66, 120, 141, 52,96, 120, 141, 52,
                 96, 120,
                 15,123, 128, 66, 120, 141,
                 141,
                 123, 128, 66, 123, 128, 66, 120, 141, 52,],
        }

#Convert to dataframe
df = pd.DataFrame(data)
print("df = \n", df)

上面的dataframe看起来是这样的:

在这里,每个id都有不同的周期,具体取决于“cycle”列。例如,
id-1具有最大11个周期。
ID-2具有最大2个周期。
ID-3具有最大6个周期。
ID-4具有最大1个周期。
ID-5具有最大9个周期。
我对'cycles'有一定的阈值限制。假设cycle_threshold = 3
如果最大循环并且id〈= cycle_threshold,则复制该组/id的最后一行,直到循环达到4。
比如说
对于id-2,由于最大周期为2(小于3),因此重复id-2的最后一行,直到周期变为4。
对于id-4,由于最大周期为1(小于3),因此重复id-4的最后一行,直到周期变为4。
组的其余部分/id保持原样。
结果如下所示:

有人能告诉我如何用Python完成这个任务吗?

1bqhqjot

1bqhqjot1#

您可以通过比较每组cycle来确定id,对于过滤组,创建MultiIndex.from_product并使用参数method='ffill'重新获取DataFrame.reindex的最后一个值:

cycle_threshold = 3
M = 4

#get maximal cycle per id
s = df.groupby('id')['cycle'].max()

#get id less or equal threshold
ids = s.index[s.le(cycle_threshold)]

#test groups by id match list ids
mask = df['id'].isin(ids)

#create MultiIndex with range(1,M + 1) for filtered groups
df1 = df[mask].set_index(['id','cycle'])
mux = pd.MultiIndex.from_product([ids, range(1, M + 1)], names=['id','cycle'])

#append new groups with sorting by id and cycle
df2 = (pd.concat([df[~mask],
                 df1.reindex(mux, method='ffill').reset_index()])
          .sort_values(['id','cycle'], ignore_index=True))

另一个想法是创建最终的MultiIndex并重新索引所有行:

cycle_threshold = 3
M = 4

s = df.groupby('id')['cycle'].max()
ids = s.index[s.le(cycle_threshold)]

mask = df['id'].isin(ids)

df2 = df.set_index(['id','cycle'])
mux = (pd.MultiIndex.from_product([ids, range(1, 5)], 
                                 names=['id','cycle']).append(df2[~mask.to_numpy()].index)
        .sort_values())
df2 = df2.reindex(mux, method='ffill').reset_index()
print (df2)
    id  cycle  Salary Children  Days
0    1      1       7       No   123
1    1      2       7      Yes   128
2    1      3       7      Yes    66
3    1      4       8      Yes    66
4    1      5       9      Yes   120
5    1      6      10       No   141
6    1      7      11       No    52
7    1      8      12      Yes    96
8    1      9      13      Yes   120
9    1     10      14      Yes   141
10   1     11      15       No    52
11   2      1       4      Yes    96
12   2      2       5       No   120
13   2      3       5       No   120
14   2      4       5       No   120
15   3      1       8       No    15
16   3      2       9      Yes   123
17   3      3      10      Yes   128
18   3      4      11       No    66
19   3      5      12       No   120
20   3      6      13      Yes   141
21   4      1       8      Yes   141
22   4      2       8      Yes   141
23   4      3       8      Yes   141
24   4      4       8      Yes   141
25   5      1       7       No   123
26   5      2       7      Yes   128
27   5      3       9       No    66
28   5      4      10       No   123
29   5      5      11      Yes   128
30   5      6      12      Yes    66
31   5      7      13      Yes   120
32   5      8      14      Yes   141
33   5      9      15       No    52
72qzrwbm

72qzrwbm2#

创建一个重复行的 Dataframe ,然后连接到原始 Dataframe ,最后对其进行排序:

import numpy as np

cycle_threshold = 3

def fix_cycle(df):
    lgt = len(df)
    if lgt < cycle_threshold:
        df1 = df.reindex(df.index[-1].repeat(cycle_threshold - lgt + 1))
        df1['cycle'] += np.arange(len(df1)) + 1
        return df1

df1 = df.groupby('id').apply(fix_cycle).droplevel(0)
out = pd.concat([df, df1]).sort_index(kind='stable', ignore_index=True)

输出:

>>> out
    id  cycle  Salary Children  Days
0    1      1       7       No   123
1    1      2       7      Yes   128
2    1      3       7      Yes    66
3    1      4       8      Yes    66
4    1      5       9      Yes   120
5    1      6      10       No   141
6    1      7      11       No    52
7    1      8      12      Yes    96
8    1      9      13      Yes   120
9    1     10      14      Yes   141
10   1     11      15       No    52
11   2      1       4      Yes    96
12   2      2       5       No   120
13   2      3       5       No   120  # <- HERE
14   2      4       5       No   120  # <- HERE
15   3      1       8       No    15
16   3      2       9      Yes   123
17   3      3      10      Yes   128
18   3      4      11       No    66
19   3      5      12       No   120
20   3      6      13      Yes   141
21   4      1       8      Yes   141
22   4      2       8      Yes   141  # <- HERE
23   4      3       8      Yes   141  # <- HERE
24   4      4       8      Yes   141  # <- HERE
25   5      1       7       No   123
26   5      2       7      Yes   128
27   5      3       9       No    66
28   5      4      10       No   123
29   5      5      11      Yes   128
30   5      6      12      Yes    66
31   5      7      13      Yes   120
32   5      8      14      Yes   141
33   5      9      15       No    52

详细信息:

>>> df1
    id  cycle  Salary Children  Days
12   2      3       5       No   120
12   2      4       5       No   120
19   4      2       8      Yes   141
19   4      3       8      Yes   141
19   4      4       8      Yes   141

相关问题