Python 如何获取同一列的n到n-3个数据并填充为同一行上的新列

Python 如何获取同一列的n到n-3个数据并填充为同一行上的新列,python,pandas,Python,Pandas,我想要操作一个数据,在这里我想要获取同一列的旧值,并作为同一行的新列输入。 我有一个名为test_df的数据帧,其中有一个列分数。基于发布日期列,我想获得当前版本的前三个版本的分数,按产品分组 Product Version score Release Android 1 5 September 23, 2008 Android 1.1 7 February 9, 2009 Android 1.5 6 April 27, 200

我想要操作一个数据,在这里我想要获取同一列的旧值,并作为同一行的新列输入。 我有一个名为test_df的数据帧,其中有一个列分数。基于发布日期列,我想获得当前版本的前三个版本的分数,按产品分组

Product  Version  score   Release
Android    1       5    September 23, 2008
Android   1.1      7   February 9, 2009
Android   1.5      6   April 27, 2009   
Android   1.6      8   September 15, 2009   
iOS       3.1.3    8   February 2, 2010
iOS       4.2.1    6   November 22, 2010     
iOS       4.2.1    9   May 7, 2012           
所以我想创建一个新的列作为score1、score2和score3。第1列的分数应为同一产品的上一版本的分数,第2列的分数应为上一版本的分数,依此类推。 如果我选择n,那么新列应该有n-1、n-2、n-3个数据

   Product  Version  score   Release             score1      score2    score3
    Android    1       5    September 23, 2008   NULL         NULL      NULL
    Android   1.1      7   February 9, 2009      5            NULL      NULL
    Android   1.5      6   April 27, 2009        7             5        NULL
    Android   1.6      8   September 15, 2009    6             7        5               
    iOS       3.1.3    8   February 2, 2010      NULL         NULL      NULL
    iOS       4.2.1    6   November 22, 2010      8           NULL      NULL
    iOS       4.2.1    9   May 7, 2012            6            8        NULL
所以,当我选择产品为Android,版本为1.1时,应该在单独的一列中获得以前版本的分数。
无论如何,我们可以在熊猫身上实现这一点。

当然,但请注意,由于“
NULL
”最有可能是指
NaN
,这将使您的
score1
等列
float
,即使
score
本身是
int

无论如何:

def trail(g, delays, column='score', defaultval=np.nan):
    for k in delays:
        newcol = f'{column}{k}'
        g[newcol] = defaultval
        g[newcol].values[k:] = g[column].values[:-k]
    return g

df = (
    df
    .sort_values(['Product', 'Release'])
    .groupby('Product')
    .apply(lambda g: trail(g, delays=range(1, 4)))
)
使用您的数据:

print(df)
   Product Version  score    Release  score1  score2  score3
0  Android       1      5 2008-09-23     NaN     NaN     NaN
1  Android     1.1      7 2009-02-09     5.0     NaN     NaN
2  Android     1.5      6 2009-04-27     7.0     5.0     NaN
3  Android     1.6      8 2009-09-15     6.0     7.0     5.0
4      iOS   3.1.3      8 2010-02-02     NaN     NaN     NaN
5      iOS   4.2.1      6 2010-11-22     8.0     NaN     NaN
6      iOS   4.2.1      9 2012-05-07     6.0     8.0     NaN
您还可以提供不同的默认值,例如
-1
,这将使新列成为
int

print(
    df
    .sort_values(['Product', 'Release'])
    .groupby('Product')
    .apply(lambda g: trail(g, defaultval=-1, delays=range(1, 4)))
)
# output:
   Product Version  score    Release  score1  score2  score3
0  Android       1      5 2008-09-23      -1      -1      -1
1  Android     1.1      7 2009-02-09       5      -1      -1
2  Android     1.5      6 2009-04-27       7       5      -1
3  Android     1.6      8 2009-09-15       6       7       5
4      iOS   3.1.3      8 2010-02-02      -1      -1      -1
5      iOS   4.2.1      6 2010-11-22       8      -1      -1
6      iOS   4.2.1      9 2012-05-07       6       8      -1
旁注:为了将数据放在df中,我复制了示例的文本(包括尾随空格)并读取为csv,如下所示:

txt = """Product  Version  score   Release
Android    1       5    September 23, 2008
Android   1.1      7   February 9, 2009
Android   1.5      6   April 27, 2009   
Android   1.6      8   September 15, 2009   
iOS       3.1.3    8   February 2, 2010
iOS       4.2.1    6   November 22, 2010     
iOS       4.2.1    9   May 7, 2012
"""
txt = '\n'.join([re.sub(' {2,}', '\t', s.strip()) for s in txt.splitlines()])
df = pd.read_csv(io.StringIO(txt), sep='\t', parse_dates=['Release'])