我有一个类似于下面的数据集,我想根据以下条件比较每一个库存项目的所有行
如果“
。
如果所有行(每个库存)的“”列为空,则对“
进行计算。
如果"value“和"item”都为null(每个库存),则
。
我可以设置这个,如果是logic逻辑,但我不知道如何将当前行与前两个行进行比较。具有转换和自定义功能的groupby是很好的建议,我想知道如何捕捉所有这些场景,或者是否有更好的方法。
下面是简化的df的样子。在我的真实数据集中,正如上面所描述的,对于相同的库存,"value“列都是空的,但是在"item”不是null下有2行,在这种情况下,需要为这2行计算“年份”列。
df1 = { 'inventory':['inv1','inv1','inv1','inv2','inv2','inv2','inv3','inv3','inv3'],
'value':['xyz','','','','','','','',''],
'item':['','304','304','','205','','','',''],
'year':[2020,2020,2020,2020,2020,2020,2019,2018,2020]}
df1=pd.DataFrame(df1)所需的输出如下所示--根据上述多个条件向标志'yes'/'no‘添加一个标志列。

发布于 2022-03-19 19:14:58
通过借用“Peter Leimbigler”和“richardec”的思想,我修改了下面的逻辑,它适用于我的实际工作情况(这比我在问题中提出的要复杂得多),因为每个库存项目有不同的行数,“值”、“项目”和“年份”的组合也不同。
我的解决方案唯一的缺点是我不能使用groupby,所以我必须创建一个循环来为每个库存项目创建单独的df,并将它们附加到一个完整的数据框架中。我希望有更好的办法。
df1 = df1.replace('', np.nan)
def make_flag_col(df,n):
comment_len = len(df.loc[df['value'].notna(),:])
jus_len = len(df.loc[df['item'].notna(),:])
maxi = df['year'].max()
n = df.shape[0]
if comment_len == 1:
df.loc[df['value'].notna(),'flag'] = 'keep'
elif comment_len >=2 or comment_len == 0:
if jus_len == 1:
df.loc[df['item'].notna(),'flag'] = 'keep'
else:
df.loc[df['year']==maxi,'flag'] = 'keep'
else:
print('out of pattern, check')
return df
l = df1['inventory'].unique().tolist()
full_df = []
for itm in l:
df_test = df1[df1['inventory']== itm].copy()
df_test = df_test.sort_values(by=['year']).reset_index()
df_row_number = df_test.shape[0]
make_flag_col(df_test,df_row_number - 1)
for i in range(len(df_test)):
row = df_test.iloc[i]
whole = list(row)
full_df.append(whole)
full_df = pd.DataFrame(full_df,columns=list(df_test.columns))
full_df['flag'].fillna('remove',inplace=True)发布于 2022-03-19 01:13:38
这其实不是很复杂。您通常需要几个groupby + transform组合。下面是一个矢量化(阅读:非常快)的解决方案:
df = df.replace('', np.nan)
cond = (
df['value'].notna() |
(df['value'].isna().groupby(df['inventory']).transform('all')
& df['item'].notna()) |
(df[['value', 'item']].isna().groupby(df['inventory']).transform('all').all(axis=1) &
(df['year'] == df.groupby('inventory')['year'].transform('max')))
)
df['flag'] = cond.map({True: 'yes', False: 'no'})输出:
>>> df
inventory value item year flag
0 inv1 xyz NaN 2020 yes
1 inv1 NaN 304 2020 no
2 inv1 NaN 304 2020 no
3 inv2 NaN NaN 2020 no
4 inv2 NaN 205 2020 yes
5 inv2 NaN NaN 2020 no
6 inv3 NaN NaN 2019 no
7 inv3 NaN NaN 2018 no
8 inv3 NaN NaN 2020 yes发布于 2022-03-19 01:18:08
您可以将规则写入自定义函数,并将其应用于每个组:
# Replace blank spaces with NaN
df1 = df1.replace('', np.nan)
def make_flag_col(subdf):
if subdf['value'].any():
return subdf['value'].notna()
elif subdf['item'].any():
return subdf['item'].notna()
else:
return subdf['year'] == subdf['year'].max()
df1['flag'] = (df1.groupby('inventory', group_keys=False)
.apply(make_flag_col)
.replace({True: 'yes', False: 'no'}))
print(df1)
inventory value item year flag
0 inv1 xyz NaN 2020 yes
1 inv1 NaN 304 2020 no
2 inv1 NaN 304 2020 no
3 inv2 NaN NaN 2020 no
4 inv2 NaN 205 2020 yes
5 inv2 NaN NaN 2020 no
6 inv3 NaN NaN 2019 no
7 inv3 NaN NaN 2018 no
8 inv3 NaN NaN 2020 yeshttps://stackoverflow.com/questions/71534576
复制相似问题