我有一张桌子
id valid
1 book
1 unknown
1 unknown
2 unknown
2 book
2 unknown
3 unknown
3 unknown
3 book
4 unknown
4 picture
我选了一些id
并测试该项是否有效。如果已经过验证,则valid
列将为“预订”。但某些项目的valid
列仍然是“未知”。我希望他们成为'书'。因为它们并非全部出现在每个组的第一位,所以我不能使用像groupby.first()
这样的东西。由于unknown
的位置不固定,我无法使用apply(pd.DataFrame.last_valid_index)
之类的内容。
由于我的原始表格变化很大,我不喜欢循环。
所需的列应如下所示:
id valid
1 book
1 book
1 book
2 book
2 book
2 book
3 book
3 book
3 book
4 unknown
4 picture
答案 0 :(得分:1)
您可以将0替换为np.nan,然后使用ffill
和bfill
df.valid=df.valid.replace(0,np.nan)
df.valid=df.groupby('id').valid.apply(lambda x : x.ffill().bfill()).fillna(0)
df
Out[1078]:
id valid
0 1 1.0
1 1 1.0
2 1 1.0
3 2 1.0
4 2 1.0
5 2 1.0
6 3 1.0
7 3 1.0
8 3 1.0
9 4 0.0
10 4 0.0
更新......操作,自更改问题
s=df.loc[df.valid=='book','id']
pd.concat([df[df.id.isin(s)].replace('unknown','book'),df[~df.id.isin(s)]])
Out[1126]:
id valid
0 1 book
1 1 book
2 1 book
3 2 book
4 2 book
5 2 book
6 3 book
7 3 book
8 3 book
9 4 unknown
10 4 picture
答案 1 :(得分:1)
以下是使用lambda
+ groupby
+ transform
的非any
解决方案:
m = df.set_index('id').valid.eq('book').groupby(level=0).transform('any')
df['valid'] = np.where(m, 'book', df.valid)
df
id valid
0 1 book
1 1 book
2 1 book
3 2 book
4 2 book
5 2 book
6 3 book
7 3 book
8 3 book
9 4 unknown
10 4 picture
答案 2 :(得分:0)
使用transform
并根据您的需要在lambda
函数中返回标量或系列:
df['valid'] = df.valid.groupby(df.id).transform(lambda g: 'book' if g.eq('book').any() else g)
df
# id valid
#0 1 book
#1 1 book
#2 1 book
#3 2 book
#4 2 book
#5 2 book
#6 3 book
#7 3 book
#8 3 book
#9 4 unknown
#10 4 picture
答案 3 :(得分:0)
一种方法是使用Categorical Data重新排序"有效"列。
然后在删除重复项后生成映射序列并将其应用于原始数据帧。
df['valid'] = df['valid'].astype('category')
df['valid'] = df['valid'].cat.set_categories(\
list(set(df['valid'])-{'Unknown'})+['Unknown'], ordered=True)
s = df.sort_values('valid').drop_duplicates('id').set_index('id')['valid']
df['valid'] = df['id'].map(s)
作为副作用,您可能会看到其他好处,例如检查有效的'中的相应项目?专栏,节省内存,提高性能。
<强>结果强>
id valid
0 1 book
1 1 book
2 1 book
3 2 book
4 2 book
5 2 book
6 3 book
7 3 book
8 3 book
9 4 unknown
10 4 unknown