【问题标题】:How to iterate a row and compare with each other?如何迭代一行并相互比较?
【发布时间】:2021-12-22 12:59:50
【问题描述】:

例如,如果名称“Mark”重复,并且与包含“Mark”的其他行相比,“Age”值或“Gender”值不同,则必须删除这些列。

创建数据框的代码:

df = pd.DataFrame({'Name' : ['Mark', 'Mark', 'Mark', 'Mark', 'Mark', 'Nick', 'Nick', 'John', 'Sunny', 'Sunny'], 
                  'Age' : ['22', '22', '25', '25', '17', '20', '20', '17', '23', '23'],
                  'Gender' : ['F', 'F', 'F', 'F', 'F', 'F', 'F', 'M', 'M', 'M']})

数据框如下:

       Name   Age   Gender
0      Mark   22    F
1      Mark   22    F
2      Mark   25    F
3      Mark   25    F
4      Mark   17    F
5      Nick   20    F
6      Nick   20    F
7      John   17    M
8      Sunny  23    M
9      Sunny  23    M

预期的输出是:

       Name   Age   Gender
0      Nick   20    F
1      Nick   20    F
2      John   17    M
3      Sunny  23    M
4      Sunny  23    M

例如在第 1 行和第 2 行中 Name 是 Mark,Age 是 22,Gender 是 F。而在第 3 行 Name 是 Mark,Age 是 25,Gender 是 F,我们可以看到 Age 有多个值,那么我们必须删除包含 Mark 的行

【问题讨论】:

  • 你自己做这个有什么问题吗?这不是真正的编程问题
  • 我不同意,@Laif。这可以在pandas 中使用分组和唯一性来完成,但这并不明显。
  • @TimRoberts 这完全有可能,我的意思是这个问题似乎与执行操作的数学方法或工具有关,而不是 OP 在他们的程序中遇到的问题。

标签: python python-3.x pandas dataframe iteration


【解决方案1】:

单行答案:

df[df.Name.isin((s:=df.drop_duplicates().groupby(['Name']).size().eq(1)).index[s])]

结果:

    Name Age Gender
5   Nick  20      F
6   Nick  20      F
7   John  17      M
8  Sunny  23      M
9  Sunny  23      M

也许值得注意的是:海象运算符仍然为变量s 分配内存,Python 的垃圾收集器最终 会取消分配。如果您需要一个 Series 来表示任何 Name 是否有不同的行,如下所示,那么值得明确分配它。

>>> s
Name
John      True
Mark     False
Nick      True
Sunny     True
dtype: bool

在您的计算中的任何其他地方,可能值得将其显式分配给您维护引用的变量。


解释:

# from the OG df
df[
   # boolean mask if the name is in
   df.Name.isin(
                # walrus-operator to temporarily hold result
                # drop the duplicate rows (duplicates name + age + gender)
                (s:=df.drop_duplicates()
                       # group on Name
                       .groupby(['Name'])
                       # after dropping duplicates, there's only one record
                       # i.e. no different age/gender records for same name
                       .size().eq(1))
                # mask on names where no-duplicates is true, drop names where false
                ).index[s]
               # pass as series to `df.Name.isin`
               )
  ]

【讨论】:

  • 当我试图运行这段代码时 df[df.Name.isin(s:=(df.drop_duplicates().groupby(['Name']).size().eq(1) ).index[s])],它返回一个错误,比如 name 's' is not defined
  • @NithinReddy 您使用的是什么版本的 Python?海象运算符 (s:=...) 是 new as of Python 3.8
  • 我使用的是 python 3.8.5,但它的返回 's' 没有定义
  • 还有其他选择吗?
  • @NithinReddy 已修复; ( 在错误的位置。
【解决方案2】:

好的,这很棘手,所以我会解释每一行。

import pandas as pd

df = pd.DataFrame({'Name' : ['Mark', 'Mark', 'Mark', 'Mark', 'Mark', 'Nick', 'Nick', 'John', 'Sunny', 'Sunny'], 
                  'Age' : ['22', '22', '25', '25', '17', '20', '20', '17', '23', '23'],
                  'Gender' : ['F', 'F', 'F', 'F', 'F', 'F', 'F', 'M', 'M', 'M']})

print(df)

# First, drop all the rows that are exact duplicates of each other.

df1 = df.drop_duplicates()
print(df1)

# If any rows that remain have a duplicate name, those need to go.

df2 = df1.duplicated('Name')
print(df2)

# Go build a DF with just the names that were duplicated.

df3 = df1[df2]['Name']
print(df3)

# Find all the rows in the original df that have a name in this list,
# invert that set, and the result is what we want.

df4 = df[~df.Name.isin(df3)]
print(df4)

这些操作中的几个可以组合成一个单行,但我认为这样会更清楚。我添加了空白行来分隔输出中的数据框。

输出:

    Name Age Gender
0   Mark  22      F
1   Mark  22      F
2   Mark  25      F
3   Mark  25      F
4   Mark  17      F
5   Nick  20      F
6   Nick  20      F
7   John  17      M
8  Sunny  23      M
9  Sunny  23      M

    Name Age Gender
0   Mark  22      F
2   Mark  25      F
4   Mark  17      F
5   Nick  20      F
7   John  17      M
8  Sunny  23      M

0    False
2     True
4     True
5    False
7    False
8    False
dtype: bool

2    Mark
4    Mark
Name: Name, dtype: object

    Name Age Gender
5   Nick  20      F
6   Nick  20      F
7   John  17      M
8  Sunny  23      M
9  Sunny  23      M

【讨论】:

  • 谢谢你,蒂姆!它正在工作。
猜你喜欢
  • 2023-01-13
  • 2015-08-08
  • 1970-01-01
  • 2017-12-22
  • 2020-04-10
  • 2016-02-10
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
相关资源
最近更新 更多