我想知道是否有一种优雅的方法,我在很长一段时间内所做的事情,我相信很粗鲁的方式。假设我们有一个数据框,其中有两列:“ 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']
是否有更优雅/更好的方式来做到这一点?任何想法/帮助将不胜感激。
答案 0 :(得分:2)
一种方法是将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