我有一个这样的数据框,
df
col1 col2
1 A
2 B
3 B
4 B
5 B
6 C
7 A
8 A
9 A
10 A
11 B
12 C
现在,如果要在col2中连续出现任意值是4(让我们说n1)替换两个(让我们说n2)值(一个从上到下,一个从下到下)的情况下,我想从上面的数据帧创建一个数据帧)的任何值都可以说('D')
我想创建一个函数,让它说f(df,n1,n2,'D'),这将返回以下数据帧,
col1 col2
1 A
2 D
3 B
4 B
5 D
6 C
7 D
8 A
9 A
10 D
11 B
12 C
我可以使用for循环来执行此操作,但是执行时间将非常长,我正在寻找pandas快捷方式/ pythonic方式来实现。
答案 0 :(得分:2)
如果col2
列中没有缺失值,则解决方案有效:
def f(df, n1, n2, val):
#count consecutive values of col2
s = df.groupby(df['col2'].ne(df['col2'].shift()).cumsum())['col2'].transform('size')
#compare by threshold and create missing values, with forward and back replacement
m1 = s >= n1
m2 = df['col2'].mask(m1).ffill(limit=n2).bfill(limit=n2).notna()
#chain masks and set val
df['col2'] = df['col2'].mask(m1 & m2, val)
return df
df1 = f(df,4,1,'D')
print (df1)
col1 col2
0 1 A
1 2 D
2 3 B
3 4 B
4 5 D
5 6 C
6 7 D
7 8 A
8 9 A
9 10 D
10 11 B
11 12 C
如果可能的话,一些缺失的值是必要的,用一些值替换它们:
def f(df, n1, n2, val):
a = df['col2'].fillna('tmp')
s = a.groupby(a.ne(a.shift()).cumsum()).transform('size')
m1 = s >= n1
m2 = a.mask(m1).ffill(limit=n2).bfill(limit=n2).notna()
df['col2'] = df['col2'].mask(m1 & m2, val)
return df
答案 1 :(得分:0)
df.groupby((df['col2'] != df['col2'].shift()).cumsum())['col2'] \
.transform(lambda x: x if len(x) < 4 else ['D']+x.iloc[1:-1].tolist()+['D'])
0 A
1 D
2 B
3 B
4 D
5 C
6 D
7 A
8 A
9 D
10 B
11 C