将一个groupby值应用于所有组

时间:2018-03-26 00:49:34

标签: python pandas group-by apply

我有一张桌子

 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

4 个答案:

答案 0 :(得分:1)

您可以将0替换为np.nan,然后使用ffillbfill

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