用新数据更新数据帧,同时保留现有的ID numb

2024-05-23 20:12:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个熊猫数据帧,可以表示为:

df = pd.DataFrame({'id':[1,2,3,4],
                   'gp':['a','a','b','b'],
                   'meta':['one','two','three','four'],
                   'matchvar':['wwww','w ww w','xxxx','xyxx'],
                   'match':[np.nan,'yes',np.nan,'no']})

…看起来像:

   id gp   meta matchvar match
0   1  a    one     wwww   NaN
1   2  a    two   w ww w   yes
2   3  b  three     xxxx   NaN
3   4  b   four     xyxx    no

可以使用groupby将数据分组到“gp”列:

for g in df.groupby(['gp']):
    print(g[1])

   id gp meta matchvar match
0   1  a  one     wwww   NaN
1   2  a  two   w ww w   yes

   id gp   meta matchvar match
2   3  b  three     xxxx   NaN
3   4  b   four     xyxx    no

如果组中的最后一行数据在“匹配”列中包含“是”,则我只想保留最后一行数据,但需要使用前一行的值更新“id”列。你知道吗

如果组中的最后一行数据在“匹配”列中包含“否”,则需要保留这两行,而不做任何更改。你知道吗

这可以概括为:

   id gp meta matchvar match
0   1  a  one     wwww   NaN  --> [row discarded]
1   2  a  two   w ww w   yes  --> 1   1  a  two   w ww w   yes [N.B. id from previous row]

…和:

   id gp   meta matchvar match
2   3  b  three     xxxx   NaN  --> 2   3  b  three     xxxx   NaN
3   4  b   four     xyxx    no  --> 3   4  b   four     xyxx    no

因此,预期输出应该是具有以下结构的数据帧:

   id gp   meta matchvar match
1   1  a    two   w ww w   yes
2   3  b  three     xxxx   NaN
3   4  b   four     xyxx    no

我可以使用.last()保留组的最后一行,但无法计算如何保留前一行的“id”值。你知道吗

如有任何建议,我们将不胜感激。你知道吗


Tags: 数据noidmatchnanmetayesthree
2条回答

当您在注释中确认每个组有2行时,您可以尝试以下逻辑:create maskm将“no”组与“yes”组分开。处理“yes”组的id,并通过同时使用drop_duplicatesconcat来选取其最后一行

m = df.match.eq('no').groupby(df.gp).transform('any')
df_yes = (df.assign(id=df.id.shift(fill_value=0))[~m]
            .drop_duplicates('gp', keep='last'))
df_final = pd.concat([df_yes, df[m]])

Out[108]:
   id gp   meta matchvar match
1   1  a    two   w ww w   yes
2   3  b  three     xxxx   NaN
3   4  b   four     xyxx    no

遵循您的逻辑,仅使用矢量化方法来保持代码的效率,我们可以执行以下操作:

mask_yes = df['match'].eq('yes') # array with True for rows with 'yes'
mask_no = df['match'].eq('no')   # array with True for rows with 'no'

# if the row is 'yes', get the shifted id, else the original id
df['id'] = np.where(mask_yes, df['id'].shift(), df['id']) 

# if a group has 'no' mark all rows as True so we can keep the whole group
mask = df.assign(indicator=mask_no).groupby('gp')['indicator'].transform('any')
# filter on groups with 'no' or only the row 'yes'
df = df[mask | mask_yes]
    id gp   meta matchvar match
1  1.0  a    two   w ww w   yes
2  3.0  b  three     xxxx   NaN
3  4.0  b   four     xyxx    no

相关问题 更多 >