我有一个像这样的pandas数据框:
Item Status
123 B
123 BW
123 W
123 NF
456 W
456 BW
789 W
789 NF
000 NF
我需要创建一个新的列Value
,它将是1或0,具体取决于Item
和Status
列中的值。值1的赋值按此顺序排列优先顺序:B
,BW
,W
,NF
。因此,使用上面的示例数据框,结果应该是:
Item Status Value
123 B 1
123 BW 0
123 W 0
123 NF 0
456 W 0
456 BW 1
789 W 1
789 NF 0
000 NF 1
使用Python 3.7。
将原始数据帧作为输入df
数据帧,以下代码将生成所需的输出:
#dictionary assigning order of priority to status values
priority_map = {'B':1,'BW':2,'W':3,'NF':4}
#new temporary column that converts Status values to order of priority values
df['rank'] = df['Status'].map(priority_map)
#create dictionary with Item as key and lowest rank value per Item as value
lowest_val_dict = df.groupby('Item')['rank'].min().to_dict()
#new column that assigns the same Value to all rows per Item
df['Value'] = df['Item'].map(lowest_val_dict)
#replace Values where rank is different with 0's
df['Value'] = np.where(df['Value'] == df['rank'],1,0)
#delete rank column
del df['rank']
我更喜欢一种方法,其状态是有序的pd.Categorical
,因为a)它是什么,b)它更具可读性:如果你有,你只需比较一个值是否等于其组的max
:
df['Status'] = pd.Categorical(df['Status'], categories=['NF', 'W', 'BW', 'B'],
ordered=True)
df['Value'] = df.groupby('Item')['Status'].apply(lambda x: (x == x.max()).astype(int))
# Item Status Value
#0 123 B 1
#1 123 BW 0
#2 123 W 0
#3 123 NF 0
#4 456 W 0
#5 456 BW 1
#6 789 W 1
#7 789 NF 0
#8 0 NF 1
通过解释我会做的一些步骤,我或许可以从概念上帮助你:
np.zeros()
或pd.fillna()
填充它groupby = pd.groupby('Item')
按Item对数据帧进行分组for name, group in groupby:
group.loc[entry]['Value'] == 0
指定值1
假设我们正在关注'123'组:
Item Status Value
-------------------------
123 B 0 (before 0, after 1)
123 BW 0
123 W 0
123 NF 0
因为行[123, 'B', 0]
根据您的标准具有最高优先级,您将其更改为[123, 'B', 1]