在熊猫中比较一组中的不同行



我有一个包含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(<max(值1(。如果这是真的,我想在一个新的列中添加一条注释来标记这一点。在这种情况下,我想要的输出是:

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获取客户端名称,但失败了。欢迎提供任何指导。感谢

编辑:我没有正确解释。注释需要从最小值为(value2(的行和最大值为(value2(的行都取客户端名称,并将注释写在这两行中的一行中。此外,我在示例中添加了更多的数据,使其更加清晰。感谢您迄今为止给出的所有答案。

我使用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和name3中发现了另一个不正确的值。

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,可以返回值1和值2的最大值的索引。loc,我们可以在该索引处获取值1和值2的值。比较这些值,使用iloc将组的最后一行指定为-1,并使用get_loc查找注释列的位置。

最新更新