Python 基于其他列中的值创建列
基本上,我想在折扣栏中填入“是”或“否”,这取决于该行所在的产品在该周是否有折扣(例如,我不希望有任何一行来考虑是否有一个星期的折扣A,而只是为该部门的产品(在大多数情况下,有一个以上的其他产品)。 我曾尝试将groupby与Sub_Dpt和Week一起使用,但都没有效果 有人知道如何解决这个问题吗 黄色列显然是代码的期望结果 下面是我使用的一些代码,我尝试先创建列,然后更新值(但可能都是错误的)(我还特意将数据帧命名为df1):Python 基于其他列中的值创建列,python,pandas,csv,dataframe,pandas-groupby,Python,Pandas,Csv,Dataframe,Pandas Groupby,基本上,我想在折扣栏中填入“是”或“否”,这取决于该行所在的产品在该周是否有折扣(例如,我不希望有任何一行来考虑是否有一个星期的折扣A,而只是为该部门的产品(在大多数情况下,有一个以上的其他产品)。 我曾尝试将groupby与Sub_Dpt和Week一起使用,但都没有效果 有人知道如何解决这个问题吗 黄色列显然是代码的期望结果 下面是我使用的一些代码,我尝试先创建列,然后更新值(但可能都是错误的)(我还特意将数据帧命名为df1): 好的,这可能不能很好地扩展,但应该很容易阅读 df1 = pd
好的,这可能不能很好地扩展,但应该很容易阅读
df1 = pd.DataFrame(data= [[ 'A', 1, 'Toys', 'Yes', ],
[ 'A', 2, 'Toys', 'No', ],
[ 'A', 3, 'Toys', 'No', ],
[ 'A', 4, 'Toys', 'Yes', ],
[ 'B', 1, 'Toys', 'No', ],
[ 'B', 2, 'Toys', 'Yes', ],
[ 'B', 3, 'Toys', 'No', ],
[ 'B', 4, 'Toys', 'Yes', ],
[ 'C', 1, 'Candy', 'No', ],
[ 'C', 2, 'Candy', 'No', ],
[ 'C', 3, 'Candy', 'Yes', ],
[ 'C', 4, 'Candy', 'Yes', ],
[ 'D', 1, 'Candy', 'No', ],
[ 'D', 2, 'Candy', 'No', ],
[ 'D', 3, 'Candy', 'No', ],
[ 'D', 4, 'Candy', 'No', ],], columns=['Product', 'Week', 'Sub_Dpt', 'Discount'])
df2 = df1.set_index(['Product', 'Week', 'Sub_Dpt'])
products = df1.Product.unique()
df1['Discount_SubDpt'] = df1.apply(lambda x: 'Yes' if 'Yes' in df2.loc[(list(products[products != x['Product']]), x['Week'], x['Sub_Dpt']), 'Discount'].tolist() else 'No', axis=1)
第一步创建一个多索引数据帧
接下来,我们将得到所有产品的列表
接下来,对于每一行,我们取出同一周和子部门并移除产品
在此列表中,如果有折扣,我们选择“是”或“否”
编辑1:
如果不想创建另一个数据帧(节省内存,但速度会慢一点)
虽然已经晚了,但现在开始吧。我在上面的评论中使用了示例df
df1['dis'] = df1['Discount'].apply(lambda x: 1 if x =="Yes" else 0)
df2 = df1.groupby(['Sub_Dpt','Week']).sum()
df2.reset_index(inplace = True)
df3 = pd.merge(df1,df2, left_on=['Sub_Dpt','Week'], right_on =['Sub_Dpt','Week'])
df3['Discount_Sb_Dpt'] = np.where(df3['dis_x'] < df3['dis_y'], 'Yes', 'No')
df3.sort_values(by=['Product'], inplace = True)
df3
df1['dis']=df1['dis']。应用(如果x==“是”,则lambda x:1,否则为0)
df2=df1.groupby(['Sub_Dpt','Week']).sum()
df2.重置索引(就地=真)
df3=pd.merge(df1,df2,左上=['Sub\u Dpt','Week'],右上=['Sub\u Dpt','Week']))
df3['dis_Sb_Dpt']=np.其中(df3['dis_x']
好的,下面的内容有点疯狂,但效果很好,所以请听好
首先,我们将构建一个NetworkX
图,如下所示
import networkx as nx
import numpy as np
import pandas as pd
G = nx.Graph()
Prods = df.Product.unique()
G.add_nodes_from(Prods)
我们现在在属于同一子部门的节点(所有产品)之间添加边。在这种情况下,由于A和B共享一个部门,而C和D共享一个部门,所以我们添加边AB和CD。如果我们在同一部门中有ABC,我们将添加AB、AC、BC。我知道,这很混乱,但请相信我
G.add_edges_from([('A','B'),('C','D')])
现在是有趣的部分。我们需要将您的折扣栏从是/否转换为1/0
df['Disc2']=np.nan
df.loc[df['Discount']=='Yes','Disc2']=1
df.loc[df['Discount']=='No','Disc2']=0
现在我们来分析数据
tab = df.pivot(index = 'Week',columns='Product',values = 'Disc2')
现在,我们这样做
tab = pd.DataFrame(np.dot(tab,nx.adjacency_matrix(G,Prods).todense()), columns=Prods,index=df.Week.unique())
tab[0].astype(bool)
df = df.merge(tab.unstack().reset_index(),left_on=['Product','Week'],right_on=['level_0','level_1'])
df['Discount_Sub_Dpt']=df[0]
print(df[['Product','Week','Sub_Dpt','Discount','Discount_Sub_Dpt']])
你可能会问,为什么要经历这个麻烦?有两个原因。第一,它更稳定。其他答案不能处理你问题的所有可能情况。第二,它比其他解决方案快得多。我希望这能有所帮助!你可以执行
分组比来映射('Week','Sub_Dpt'))
仅当折扣为“是”时,才能添加到产品列表中
然后使用列表理解来检查除了所讨论的产品之外是否还有折扣。最后,将布尔序列结果映射到“是”/“否”
数据来自@SahilPuri
# GroupBy only when Discount == Yes
g = df1[df1['Discount'] == 'Yes'].groupby(['Week', 'Sub_Dpt'])['Product'].unique()
# calculate index by row
idx = df1.set_index(['Week', 'Sub_Dpt']).index
# construct list of Booleans according to criteria
L = [any(x for x in g.get(i, []) if x!=j) for i, j in zip(idx, df1['Product'])]
# map Boolean to strings
df1['Discount_SubDpt'] = pd.Series(L).map({True: 'Yes', False: 'No'})
print(df1)
Product Week Sub_Dpt Discount Discount_SubDpt
0 A 1 Toys Yes No
1 A 2 Toys No Yes
2 A 3 Toys No No
3 A 4 Toys Yes Yes
4 B 1 Toys No Yes
5 B 2 Toys Yes No
6 B 3 Toys No No
7 B 4 Toys Yes Yes
8 C 1 Candy No No
9 C 2 Candy No No
10 C 3 Candy Yes No
11 C 4 Candy Yes No
12 D 1 Candy No No
13 D 2 Candy No No
14 D 3 Candy No Yes
15 D 4 Candy No Yes
有点困惑…你能再解释一下黄色栏的逻辑是什么吗?因此黄色栏将查看同一子部门中的所有产品,不包括该特定行中的产品。因此,对于第一行,它将查看子部门的玩具,并查看该子部门在该特定周内是否有折扣,但它将ludes Product A。因此,每周该列确定是否有折扣,但从该确定中排除它自己的行。哦,我明白了,这很有趣。你能发布代码来创建该数据框吗?我只是从csv文件输入数据,但就是这样:df1=pd.read_csv(“1_u.csv”,error_bad_lines=False,header=0,dtype={“总销售额”:float,“库存描述”:str,“供应商”:float,“Dpt”:str,“Dpt描述”:str,“Sub_Dpt”:str,“Sub_Dpt”:str,“Sub_描述”:str,“Sub_Class”:str,“Sub_Class”:str,“库存类型”:str,“周”:str,“季节”:str,“折扣”:str,“销售非广告”:float,“销售广告”:float,“前一周”:float})df1=df1[np.isfinite(df1['SKU_编号])]我对它并不感到兴奋,但它应该涵盖大多数情况。我正在研究一些有望运行的东西faster@SahilPuri。这对我不起作用,新列只是没有固定,我忘了将其转换为列表。@SahilPuri这是有效的!我遇到的唯一问题是当我尝试使用我的csv时。我得到以下输出:KeyError:('100',u'出现在索引0'处)再次感谢您!这对我的CSV非常有效感谢您花时间编写此解决方案。唯一的一点是,我发布的示例过于简单化,因此我有100个产品共享同一部门。因此,如果不进行大量手动工作,第二步将不适用。实际上,muchI无法编写此解决方案如果有帮助的话,请给我一个脚本
tab = pd.DataFrame(np.dot(tab,nx.adjacency_matrix(G,Prods).todense()), columns=Prods,index=df.Week.unique())
tab[0].astype(bool)
df = df.merge(tab.unstack().reset_index(),left_on=['Product','Week'],right_on=['level_0','level_1'])
df['Discount_Sub_Dpt']=df[0]
print(df[['Product','Week','Sub_Dpt','Discount','Discount_Sub_Dpt']])
# GroupBy only when Discount == Yes
g = df1[df1['Discount'] == 'Yes'].groupby(['Week', 'Sub_Dpt'])['Product'].unique()
# calculate index by row
idx = df1.set_index(['Week', 'Sub_Dpt']).index
# construct list of Booleans according to criteria
L = [any(x for x in g.get(i, []) if x!=j) for i, j in zip(idx, df1['Product'])]
# map Boolean to strings
df1['Discount_SubDpt'] = pd.Series(L).map({True: 'Yes', False: 'No'})
print(df1)
Product Week Sub_Dpt Discount Discount_SubDpt
0 A 1 Toys Yes No
1 A 2 Toys No Yes
2 A 3 Toys No No
3 A 4 Toys Yes Yes
4 B 1 Toys No Yes
5 B 2 Toys Yes No
6 B 3 Toys No No
7 B 4 Toys Yes Yes
8 C 1 Candy No No
9 C 2 Candy No No
10 C 3 Candy Yes No
11 C 4 Candy Yes No
12 D 1 Candy No No
13 D 2 Candy No No
14 D 3 Candy No Yes
15 D 4 Candy No Yes