Python 使用相应的过去索引值和特定的唯一列值填充新的dataframe列

Python 使用相应的过去索引值和特定的唯一列值填充新的dataframe列,python,python-3.x,pandas,for-loop,dataframe,Python,Python 3.x,Pandas,For Loop,Dataframe,我想知道是否有一种优雅的方式,我做了很长时间,我相信非常粗糙的方式。假设我们有一个数据框,其中有两列:“col1”和“col2”。行数为13'Col1'包含三个变量:“a”、“b”和“c”col2'包含随机数值。现在,我想创建一个名为“teststat”的新列,该列包含“col2”中包含的值,该值在“col1”中的变量上次出现时包含,或者如果是第一次出现,则等于当前值。例如,如果“a”出现在第0、1、4、6和12行,并且在这些索引位置的col2值为32、432、56、4和34,则这些位置的测试统

我想知道是否有一种优雅的方式,我做了很长时间,我相信非常粗糙的方式。假设我们有一个数据框,其中有两列:“col1”和“col2”。行数为13'Col1'包含三个变量:“a”、“b”和“c”col2'包含随机数值。现在,我想创建一个名为“teststat”的新列,该列包含“col2”中包含的值,该值在“col1”中的变量上次出现时包含,或者如果是第一次出现,则等于当前值。例如,如果“a”出现在第0、1、4、6和12行,并且在这些索引位置的col2值为32、432、56、4和34,则这些位置的测试统计值应为32、32、432、56和4

我想要的示例数据集:

index   col1    teststat    col2
  0      a         32.0       32
  1      a         32.0      432
  2      b        433.0      433
  3      c          4.0        4
  4      a        432.0       56
  5      c          4.0       64
  6      a         56.0        4
  7      b        433.0      535
  8      c         64.0      643
  9      c        643.0      356
 10      b        535.0       32
 11      b         32.0      535
 12      a          4.0       34
我使用了以下代码,该代码使用存储“a”、“b”、“c”中特定值的索引的逻辑,然后使用for循环编写单个代码,但我可以看到,在放大时,这可能会成为一个问题,例如,如果“col1”中只有3个唯一值,而我们有500多个单独的唯一值。我想要一个解决方案/逻辑,说明可以为该场景做些什么。我在下面添加了代码:

单元格[1]

for vals in list(df['col1'].unique()):
    if vals=='a':
        idxa = df.index[df['col1']=='a']
    if vals=='b':
        idxb = df.index[df['col1']=='b']
    if vals=='c':
        idxc = df.index[df['col1']=='c']    
单元格[2]

for i in range(len(idxa)):
    if i==0:
        df.loc[idxa[i],'test_stat']=df.loc[idxa[i],'col2']
    else:
        df.loc[idxa[i],'test_stat']=df.loc[idxa[i-1],'col2']


for i in range(len(idxb)):
    if i==0:
        df.loc[idxb[i],'test_stat']=df.loc[idxb[i],'col2']
else:
    df.loc[idxb[i],'test_stat']=df.loc[idxb[i-1],'col2']

for i in range(len(idxc)):
    if i==0:
        df.loc[idxc[i],'test_stat']=df.loc[idxc[i],'col2']
    else:
        df.loc[idxc[i],'test_stat']=df.loc[idxc[i-1],'col2']        

有没有更优雅/更好的方法?任何想法/帮助都将不胜感激。

一种方法是将
groupby
shift
一起使用

df['teststat'] = df.groupby('col1')['col2'].shift(1).fillna(df['col2'])

print(df[['col1', 'teststat', 'col2']])

    col1    teststat    col2
0      a        32.0      32
1      a        32.0     432
2      b       433.0     433
3      c         4.0       4
4      a       432.0      56
5      c         4.0      64
6      a        56.0       4
7      b       433.0     535
8      c        64.0     643
9      c       643.0     356
10     b       535.0      32
11     b        32.0     535
12     a         4.0      34
编辑

关于你补充的问题:

比如说,我需要另一列“teststat2”,它给出“col1”中某个特定值的最后两个值之间的差值

您可以只做以下操作

df['teststat2'] = df['col2'] - df['teststat']
df.loc[df['teststat2'] == 0, 'teststat2'] = df['col2']
print(df)

    col1    teststat    col2    teststat2
0      a        32.0      32         32.0
1      a        32.0     432        400.0
2      b       433.0     433        433.0
3      c         4.0       4          4.0
4      a       432.0      56       -376.0
5      c         4.0      64         60.0
6      a        56.0       4        -52.0
7      b       433.0     535        102.0
8      c        64.0     643        579.0
9      c       643.0     356       -287.0
10     b       535.0      32       -503.0
11     b        32.0     535        503.0
12     a         4.0      34         30.0

一种方法是将
groupby
shift
一起使用

df['teststat'] = df.groupby('col1')['col2'].shift(1).fillna(df['col2'])

print(df[['col1', 'teststat', 'col2']])

    col1    teststat    col2
0      a        32.0      32
1      a        32.0     432
2      b       433.0     433
3      c         4.0       4
4      a       432.0      56
5      c         4.0      64
6      a        56.0       4
7      b       433.0     535
8      c        64.0     643
9      c       643.0     356
10     b       535.0      32
11     b        32.0     535
12     a         4.0      34
编辑

关于你补充的问题:

比如说,我需要另一列“teststat2”,它给出“col1”中某个特定值的最后两个值之间的差值

您可以只做以下操作

df['teststat2'] = df['col2'] - df['teststat']
df.loc[df['teststat2'] == 0, 'teststat2'] = df['col2']
print(df)

    col1    teststat    col2    teststat2
0      a        32.0      32         32.0
1      a        32.0     432        400.0
2      b       433.0     433        433.0
3      c         4.0       4          4.0
4      a       432.0      56       -376.0
5      c         4.0      64         60.0
6      a        56.0       4        -52.0
7      b       433.0     535        102.0
8      c        64.0     643        579.0
9      c       643.0     356       -287.0
10     b       535.0      32       -503.0
11     b        32.0     535        503.0
12     a         4.0      34         30.0

回答得好,
.shift(1)
应该是
.shift()
:)非常感谢您的解决方案。它是有效的,从上面我可以理解的是,首先将索引移动1,以便根据col1对col2值进行分组,然后将这些值填充到“teststat”列中。好的,现在我有另一个问题,是这个问题的延伸。比如说,我需要另一列“teststat2”,它给出“col1”中某个特定值的最后两个值之间的差值。从我的理解来看,移位只是移位索引,而不是存储索引。感谢您的帮助。类似“a”的字符出现在第0、1、4、6和12行,在这些索引位置的col2值是32、432、56、4和34,那么teststat2值应该是32(=32)、400(=432-32)、-376(=56-432)和30(=34-4)。除非我遗漏了什么,否则这似乎与从
df['teststat]
减去
df['col2]
是一样的。然后您可以只更新
df['teststat2]
为0的值。请看我的编辑。是的,本刚刚检查了你的编辑。工作起来很有魅力。谢谢你的帮助。但现在我必须加强对转型和分组操作的控制。非常方便。回答得好,
.shift(1)
应该是
.shift()
:)非常感谢您的解决方案。它是有效的,从上面我可以理解的是,首先将索引移动1,以便根据col1对col2值进行分组,然后将这些值填充到“teststat”列中。好的,现在我有另一个问题,是这个问题的延伸。比如说,我需要另一列“teststat2”,它给出“col1”中某个特定值的最后两个值之间的差值。从我的理解来看,移位只是移位索引,而不是存储索引。感谢您的帮助。类似“a”的字符出现在第0、1、4、6和12行,在这些索引位置的col2值是32、432、56、4和34,那么teststat2值应该是32(=32)、400(=432-32)、-376(=56-432)和30(=34-4)。除非我遗漏了什么,否则这似乎与从
df['teststat]
减去
df['col2]
是一样的。然后您可以只更新
df['teststat2]
为0的值。请看我的编辑。是的,本刚刚检查了你的编辑。工作起来很有魅力。谢谢你的帮助。但现在我必须加强对转型和分组操作的控制。非常方便。