Python Pandas条件标记

时间:2018-04-23 20:34:53

标签: python pandas if-statement conditional-statements

使用python pandas dataframe df:

product_id |transaction_id | category | color
234          54              A           black
349          54              B           silver
213          46              A           silver
490          46              A           black
245          87              A           black
249          87              B           black
294          87              A           silver

我想标记具有相同颜色的A和B类别的transaction_ID。因此,在上面的场景中,交易87具有产品A黑色和产品B黑色。

期望的输出:

product_id |transaction_id | category | color  | flag
234          54              A           black
349          54              B           silver
213          46              A           silver
490          46              A           black
245          87              A           black    X
249          87              B           black    X
294          87              A           silver   X

我试图在类别和颜色之间创建一个唯一的键,然后groupby,但它变得凌乱,我仍然需要手动完成它。必须有一个更简单的方法。

df['key']=df['category']&df['color']

df['transaction_analysis']= df.groupby('transaction_id').key.transform(lambda x : '&'.join(set(x)))

2 个答案:

答案 0 :(得分:1)

不确定是否更简单,但肯定更清洁。您可以在simple_expr = "x" block_expr = "x" sep block expression = simple_expr / block_expr if_stmt = "if" sep simple_expr sep block groupbytransaction_id,找到category的唯一颜色,然后取消堆叠。

在此之后,生成标志值的映射并稍后分配给unique

df

v = (
    df.groupby(['transaction_id', 'category'])
      .color
      .unique()
      .unstack(fill_value=set())
)
m = {
  k : 'X' if set(x).intersection(y) else '' for k, x, y in zip(v.index, v.A, v.B)
}    
df['flag'] = df['transaction_id'].map(m)

答案 1 :(得分:1)

这是另一种方法:

import pandas as pd

df = pd.DataFrame({'category': ['A', 'B', 'A', 'A', 'A', 'B', 'A'],
                   'color': ['black', 'silver', 'silver', 'black', 
                             'black', 'black', 'silver'],
                   'product_id': [234, 349, 213, 490, 245, 249, 294],
                   'transaction_id': [54, 54, 46, 46, 87, 87, 87]})

pivoted = df.pivot_table(index=['transaction_id','color'], columns=['category'], 
                         values='product_id')
transaction_color_mask = pd.notnull(pivoted).all(axis=1)
transaction_map = transaction_color_mask.groupby(level=0).any().map({True:'X',False:''})
df['flag'] = df['transaction_id'].map(transaction_map)
print(df)

产量

  category   color  product_id  transaction_id flag
0        A   black         234              54     
1        B  silver         349              54     
2        A  silver         213              46     
3        A   black         490              46     
4        A   black         245              87    X
5        B   black         249              87    X
6        A  silver         294              87    X

主要思想是使用pivot_table公开要在行中进行比较的值:

In [182]: pivoted
Out[182]: 
category                   A      B
transaction_id color               
46             black   490.0    NaN
               silver  213.0    NaN
54             black   234.0    NaN
               silver    NaN  349.0
87             black   245.0  249.0
               silver  294.0    NaN

现在我们可以找到类别AB具有相同颜色的行:

In [183]: transaction_color_mask = pd.notnull(pivoted).all(axis=1); transaction_color_mask
Out[183]: 
transaction_id  color 
46              black     False
                silver    False
54              black     False
                silver    False
87              black      True
                silver    False
dtype: bool

transaction_id分组以查找与True行相关联的transaction_id

In [184]: transaction_color_mask.groupby(level=0).any()
Out[184]: 
transaction_id
46    False
54    False
87     True
dtype: bool

然后将True映射到'X'False以清空字符串:

In [185]: transaction_color_mask.groupby(level=0).any().map({True:'X',False:''})
Out[185]: 
transaction_id
46     
54     
87    X
dtype: object

最后,将结果与df重新组合:df['flag'] = df['transaction_id'].map(transaction_map)会产生所需的结果。