使用相应的过去索引值和特定的唯一列值填充新的数据框列

时间:2018-07-11 06:20:00

标签: python python-3.x pandas for-loop dataframe

我想知道是否有一种优雅的方法,我在很长一段时间内所做的事情,我相信很粗鲁的方式。假设我们有一个数据框,其中有两列:“ col1”,“ col2”。行数为13。“ Col1”包含三个变量:“ a”,“ b”和“ c”。 'col2'包含随机数值。现在,我想创建一个名为“ teststat”的新列,该列包含上次发生时“ col1”中变量“ col2”中包含的值,或者如果它是首次出现,则等于当前值。例如,如果在行0、1、4、6和12中出现“ a”,并且它们在这些索引位置的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']        

是否有更优雅/更好的方式来做到这一点?任何想法/帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

一种方法是将groupbyshift一起使用。

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