Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基于其他列中的值创建列_Python_Pandas_Csv_Dataframe_Pandas Groupby - Fatal编程技术网

Python 基于其他列中的值创建列

Python 基于其他列中的值创建列,python,pandas,csv,dataframe,pandas-groupby,Python,Pandas,Csv,Dataframe,Pandas Groupby,基本上,我想在折扣栏中填入“是”或“否”,这取决于该行所在的产品在该周是否有折扣(例如,我不希望有任何一行来考虑是否有一个星期的折扣A,而只是为该部门的产品(在大多数情况下,有一个以上的其他产品)。 我曾尝试将groupby与Sub_Dpt和Week一起使用,但都没有效果 有人知道如何解决这个问题吗 黄色列显然是代码的期望结果 下面是我使用的一些代码,我尝试先创建列,然后更新值(但可能都是错误的)(我还特意将数据帧命名为df1): 好的,这可能不能很好地扩展,但应该很容易阅读 df1 = pd

基本上,我想在折扣栏中填入“是”或“否”,这取决于该行所在的产品在该周是否有折扣(例如,我不希望有任何一行来考虑是否有一个星期的折扣A,而只是为该部门的产品(在大多数情况下,有一个以上的其他产品)。 我曾尝试将groupby与Sub_Dpt和Week一起使用,但都没有效果

有人知道如何解决这个问题吗

黄色列显然是代码的期望结果

下面是我使用的一些代码,我尝试先创建列,然后更新值(但可能都是错误的)(我还特意将数据帧命名为df1):


好的,这可能不能很好地扩展,但应该很容易阅读

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