比较熊猫组中的不同行

时间:2020-10-26 17:08:45

标签: python pandas pandas-groupby

我有一个5列多行的数据框。它显示客户,产品,日期和一些值。我需要比较相同产品和相同日期的值。分组后,我得到这样的东西:

client  product   date          value1  value2
name1   p1        01/01/2001    10      15
name2   p1        01/01/2001    14      19
name3   p1        01/01/2001    18      22
name2   p2        01/01/2001    10      15
name4   p2        01/01/2001    14      19
name5   p2        01/01/2001    18      22
name1   p1        02/01/2001    10      18
name2   p1        02/01/2001    14      19
name3   p1        02/01/2001    18      22
name1   p2        02/01/2001    10      15
name4   p2        02/01/2001    14      19
name5   p2        02/01/2001    18      22

我现在要做的是获取每个组中的value2列的最小值和value1列的最大值,并检查min(value2)

client  product   date          value1  value2  comments
name1   p1        01/01/2001    10      15
name2   p1        01/01/2001    14      19
name3   p1        01/01/2001    18      22      name1 to name3
name2   p2        01/01/2001    10      15
name4   p2        01/01/2001    14      19
name5   p2        01/01/2001    18      22      name2 to name5
name1   p1        02/01/2001    10      18
name2   p1        02/01/2001    14      19
name3   p1        02/01/2001    18      22
name1   p2        02/01/2001    10      15
name4   p2        02/01/2001    14      19
name5   p2        02/01/2001    18      22      name1 to name5

我是熊猫的新手,我完全不知道该怎么做。我设法做到了这段代码,但是并没有真正实现我想要的功能。它用最小值填充了整个新列(可能不需要)。此外,它与所有其他列进行比较,而不是与最大值进行比较。

df = pd.read_csv("data.txt")
dfg = df.groupby(["product", "date"])
df = df.assign(min2=dfg["value2"].transform(min))
df["comment"] = np.where(df["value1"] > df["min2"], 1, 0)

最后,我尝试使用loc来获取客户端名称,但是失败了。欢迎任何指导。谢谢

编辑:我没有正确解释。注释需要从具有min(value2)的行和具有max(value2)的行中获取客户端名称,并在这两行之一中编写注释。另外,我在示例中添加了更多数据,因此更加清晰。谢谢您到目前为止的所有回答。

2 个答案:

答案 0 :(得分:0)

我使用loc相应地对数据帧进行切片。

df['comments'] = np.nan
for p in set(df['product']):
    max_ = df.loc[df['product'] == p,'value1'].max()
    min_ = df.loc[df['product'] == p,'value2'].min()
    if  max_ > min_:
        value_1 = df.loc[(df['product']== p) & (df['value1'] == max_),'client'] #getting the client(s) of the maximum value1
        value_2 = df.loc[(df['product']== p) & (df['value2'] == min_),'client'] #getting the client(s) of the maximum value2
        #commenting according to each name
        for v2 in value_2:
            for v1 in value_1:
                locking = (df['product'] == p) & (df['client'] == v1)
                df.loc[locking,'comments'] = v2 + ' to ' + v1
df

    client  product date        value1  value2  comments
0   name1   p1      01/01/2001  10      15      NaN
1   name2   p1      01/01/2001  14      19      NaN
2   name3   p1      01/01/2001  18      22      name1 to name3
3   name2   p2      01/01/2001  10      15      NaN
4   name4   p2      01/01/2001  14      19      NaN
5   name5   p2      01/01/2001  18      22      name1 to name5
6   name1   p1      02/01/2001  10      18      NaN
7   name2   p1      02/01/2001  14      19      NaN
8   name3   p1      02/01/2001  18      22      name1 to name3
9   name1   p2      02/01/2001  10      15      NaN
10  name4   p2      02/01/2001  14      19      NaN
11  name5   p2      02/01/2001  18      22      name1 to name5

此代码找到了4行而不是3行来插入注释。我相信这是正确的方法,因为在索引行8中,它在name1 vs name3中发现了另一个不正确的值。

答案 1 :(得分:0)

IIUC,您可以使用以下自定义函数:

def f(x):
    x['comments'] = np.nan
    max_v1_idx = x['value1'].idxmax()
    min_v2_idx = x['value2'].idxmin()
    max_v1 = x.loc[max_v1_idx, 'value1']
    min_v2 = x.loc[min_v2_idx, 'value2']
    
    if min_v2 < max_v1:
        x.iloc[-1, x.columns.get_loc('comments')] = x.loc[min_v2_idx, 'client'] + ' to ' +  x.loc[max_v1_idx, 'client'] 
    
    return x
        
df.groupby(['product','date'])\
  .apply(f)

输出:

   client product        date  value1  value2        comments
0   name1      p1  01/01/2001      10      15             NaN
1   name2      p1  01/01/2001      14      19             NaN
2   name3      p1  01/01/2001      18      22  name1 to name3
3   name2      p2  01/01/2001      10      15             NaN
4   name4      p2  01/01/2001      14      19             NaN
5   name5      p2  01/01/2001      18      22  name2 to name5
6   name1      p1  02/01/2001      10      18             NaN
7   name2      p1  02/01/2001      14      19             NaN
8   name3      p1  02/01/2001      18      22             NaN
9   name1      p2  02/01/2001      10      15             NaN
10  name4      p2  02/01/2001      14      19             NaN
11  name5      p2  02/01/2001      18      22  name1 to name5

详细信息:

使用groupby从数据框中获取记录组。使用idxminidxmax可以返回value1和value2的最大值的索引。 loc我们可以在该索引处获取value1和value2的值。比较这些值,然后使用iloc将组的最后一行分配为-1,并使用get_loc查找注释列的位置。