pandas 如何使用 groupby 和 loc

时间:2021-07-02 21:24:38

标签: python pandas dataframe

我有一个数据框:

data = {'fruit': ['pear','pear','banana', 'pear', 'pear','apple', 'melon', 'cherry','cherry'],
'country': ['russia','usa', 'russia', 'russia','ghana','russia', 'russia', 'albania','andorra'],
'id': ['011','011','011', '011', '011','011', '6', '6','6'],
'month': ['march','march', 'november', 'march', 'january','january', 'march', 'january','july']       
}
df = pd.DataFrame(data, columns = ['fruit','country', 'id', 'month'])

enter image description here

我想通过 'id' 删除每个组中的连续重复项。 我有

cols = ["fruit"]
de_dup = a[cols].loc[(df[cols].shift() != df[cols]).any(axis=1)]

但不使用 groupby。 我如何使用 groupby('id') 运行它,有人能看到问题吗?

输出数据帧:

enter image description here

2 个答案:

答案 0 :(得分:1)

另一种没有 groupby 的方法:

df.assign(dupkey=(df[cols].shift() != df[cols]).cumsum()).drop_duplicates('dupkey')

输出:

    fruit  country   id     month  dupkey
0    pear   russia  011     march       1
2  banana   russia  011  november       2
3    pear   russia  011     march       3
5   apple   russia  011   january       4
6   melon   russia    6     march       5
7  cherry  albania    6   january       6

和 groupby

df.groupby((df[cols].shift() != df[cols]).cumsum().squeeze(), as_index=False).first()

输出:

    fruit  country   id     month
0    pear   russia  011     march
1  banana   russia  011  november
2    pear   russia  011     march
3   apple   russia  011   january
4   melon   russia    6     march
5  cherry  albania    6   january

答案 1 :(得分:1)

为了避免使用 groupby,您可以简单地同时比较“id”和“fruit”,如下所示:

subset = df[["id", "fruit"]]

# marks all contiguous repeats of "id" and "fruit" as True
contiguous_duplicates = (subset == subset.shift()).all(axis=1)
new_df = df.loc[~contiguous_duplicates, :]

print(new_df)
    fruit  country   id     month
0    pear   russia  011     march
2  banana   russia  011  november
3    pear   russia  011     march
5   apple   russia  011   january
6   melon   russia    6     march
7  cherry  albania    6   january

说明:

  • subset = df[["id", "fruit"]] 我们在这里所做的只是抓取我们想要比较的所有相关列
>>> print(subset)
    id   fruit
0  011    pear
1  011    pear
2  011  banana
3  011    pear
4  011    pear
5  011   apple
6    6   melon
7    6  cherry
8    6  cherry
  • (subset == subset.shift()) 所做的就是将所有行向下移动一个并将其与原始子集进行比较。当我们比较它们时,它会返回一个布尔数据框(与 subset 大小相同),其 True/False 值对应于该值是否与来自同一行/列的前一个值相同。
      id  fruit
0  False  False
1   True   True
2   True  False
3   True  False
4   True   True
5   True  False
6  False  False
7   True  False
8   True   True

在上面的框架中,您可以看到我们将移位子集的每个值与原始子集进行了比较。如果值为 True,则表示它与前一行中的值相同。请注意,由于重复的“id”值,“id”列有很多 True 值。

  • .all(axis=1) 现在我们有一个布尔数据框,我们想检查整行是否为 True,如果它们是,这意味着整行与数据框中的前一行相同。这些是我们想要删除的行,因为它们是“连续重复”。
0    False
1     True
2    False
3    False
4     True
5    False
6    False
7    False
8     True
dtype: bool

现在这个 Series 表示前一个布尔数据帧在整行中为 True 的位置。由于这些是我们想要删除(而不是保留)的行,我们需要翻转这个布尔值 Series,这可以使用波浪号 ~ 运算符完成:

  • df.loc[~contiguous_duplicates, :] 反转上述布尔值 Series 并使用它从原始数据框中选择行。