我有大约50列,这些列的行是重复的,具有相似的值。例如:
Idx Series Col1 Col2 Col3 Col4 Col5 ..... Col50
0 A 1
1 A 1
2 A 1
3 A 1
4 B 3 2 3
5 B 3 2 3
6 B 3 2 3
7 B 3 2 3
8 C 4 1
9 C 4 1
10 C 4 1
11 C 4 1
我想根据其位置从重复值中保留一个值,并将其他值更改为"0">
因此,如果值为"4",则保留第4位的值,前三位将更改为"0"。类似地,如果值为"1",则保留第一个值,其余值将更改为"0"。
输出列为:
Idx Series Col1 Col2 Col3 Col4 Col5 ..... Col50
0 A 1
1 A 0
2 A 0
3 A 0
4 B 0 0 0
5 B 0 2 0
6 B 3 0 3
7 B 0 0 0
8 C 0 1
9 C 0 0
10 C 0 0
11 C 4 0
任何帮助都将不胜感激。
谢谢。。
由于您的DataFrame不包含NaN值,我假设:
- 列Col1到Col50属于对象类型
- 它们包含字符串数据,可以是空字符串,也可以是字符串包含一个数字字符
要获得预期结果,请定义以下两个函数:
-
应用于要转换的每列的函数:
def cnv(col): return col.groupby((col != col.shift()).cumsum()).apply(cnv2)
-
要应用于当前列中每组的函数:
def cnv2(grp): if grp.str.isnumeric().all(): ind = grp.index[0] val = int(grp.iloc[0]) return grp.where(grp.index == val + ind - 1, '0') else: return grp
然后将cnv函数应用于要转换的列,保存结果返回相同的列:
df.loc[:, 'Col1':'Col50'] = df.loc[:, 'Col1':'Col50'].apply(cnv)
结果是:
Idx Series Col1 Col2 Col3 Col5 Col50
0 0 A 1
1 1 A 0
2 2 A 0
3 3 A 0
4 4 B 0 0 0
5 5 B 0 2 0
6 6 B 3 0 3
7 7 B 0 0 0
8 8 C 0 1
9 9 C 0 0
10 10 C 0 0
11 11 C 4 0
让我们做
df2 = df.replace(r'^s*$', np.nan, regex=True)
new_df = (df2.assign(**df2.filter(regex='Col')
.where(lambda x: x.eq(df.groupby('Series')
.cumcount()
.add(1),
axis=0) | x.isna() ,
0)
)
.fillna('') # I recommend remove this line
)
print(new_df)
输出
Idx Series Col1 Col2 Col3
0 0 A 1
1 1 A 0
2 2 A 0
3 3 A 0
4 4 B 0 0
5 5 B 0 2
6 6 B 3 0
7 7 B 0 0
8 8 C 0
9 9 C 0
10 10 C 0
11 11 C 4