【问题标题】:Get unique values from a column using Python使用 Python 从列中获取唯一值
【发布时间】:2015-03-25 16:46:42
【问题描述】:

我正在尝试从“名称”列中获取“性别”列中每个不同值的唯一值。

以下是示例数据: 示例 input_file_data:

index,name,gender,alive
1,Adam,Male,Y
2,Bella,Female,N
3,Marc,Male,Y
1,Adam,Male,N

当我给出与“性别”相对应的值时,我可以得到它,例如,在下面的代码中给出“男性”:

filtered_data = filter(lambda person: person["gender"] == "Male", input_file_data)
reader = (dict((k, v.strip()) for k, v in row.items() if v) for row in filtered_data)
countt = [rec[gender] for rec in reader]
final1 = input_file_name + ".txt", "gender", "Male"
output1 = str(final1).replace("(", "").replace(")", "").replace("'","").replace(", [{", " -- [").replace("}", "")
final2 = set(re.findall(r"name': '(.*?)'", str(filtered_data)))
final_count = len(final2)
output = str(final_count) + " occurrences", str(final2)
output2 = output1, str(output)
output_final = str(output2).replace('\\', "").replace('"',"").replace(']"', "]").replace("set", "").replace("(", "").replace(")", "").replace("'","").replace(", [{", " -- [").replace("}", "")
output_final = output_final + "\n"

当前输出:

input_file_name.txt, gender, Male, 2 occurrences, [Adam,Marc]

预期输出:

input_file_name.txt, gender, Male, 2 occurrences, [Adam,Marc], Female, 1 occurrences [Bella]

应该为每个不同的性别值(没有硬编码)显示所有唯一出现的名称。我也不想使用熊猫。非常感谢任何帮助。

PS- 我有多个文件,并非所有文件都有相同的列。所以我不能对它们进行硬编码。此外,所有文件都有一个“名称”列,但并非所有文件都有一个“性别”列。这个脚本应该适用于任何其他列,如“index”或“alive”或其他任何内容,而不仅仅是性别。

【问题讨论】:

  • 为什么不想使用 pandas?它就是为这类事情而设计的。它有一点学习曲线,但绝对值得学习。
  • @acushner 还有几个人将运行这个脚本。他们比我对 Python 更陌生,安装包本身对他们来说是新的。所以我更喜欢坚持默认安装的软件包,如果这有意义的话。
  • 这有点道理。但要在熊猫中做你想做的事,基本上是:df = pd.read_csv(csvfile); print df[df.gender == 'Male']; print df[df.gender == 'Female']。这似乎总体上更容易。但无论哪种方式都有效。
  • 另外,另一件事。也许考虑使用 anaconda。默认情况下,它有 pandas 和其他很棒的工具。 store.continuum.io/cshop/anaconda(免费)

标签: python csv unique


【解决方案1】:

为此,我将使用 csv 模块以及来自 collectionsdefaultdict。假设它存储在一个名为 test.csv 的文件中:

>>> import csv
>>> from collections import defaultdict
>>> with open('test.csv', 'rb') as fin: data = list(csv.reader(fin))[1:]
>>> gender_dict = defaultdict(set)
>>> for idx, name, gender, alive in data:
    gender_dict[gender].add(name)

>>> gender_dict
defaultdict(<type 'set'>, {'Male': ['Adam', 'Marc'], 'Female': ['Bella']})

你现在有一本字典。每个键都是来自性别列的唯一值。每个值都是一个集合,因此您只会获得唯一的项目。请注意,我们添加了两次'Adam',但在结果集中只看到一个。

您不需要defaultdict,但它允许您使用更少的样板代码来检查密钥是否存在。

编辑:这可能有助于更好地了解数据本身。鉴于您的代码,我可以做出以下假设:

  • input_file_data 是一个包含字典的可迭代(列表、元组等)。

  • 每个字典都包含一个'gender' 键。如果它没有至少包含'gender',那么在尝试过滤它时会出现关键错误。

  • 每个字典都有一个'name' 键,看起来像。

与其做所有的正则表达式,不如这样做?

>>> gender_dict = {'Male': set(), 'Female': set()}
>>> for item in input_file_data:
        gender_dict[item['gender']].add(item['name'])

如果不是每个条目都有名称,您可以使用 item.get('name') 代替 item['name']

编辑 #2:好的,您需要做的第一件事就是让您的数据处于一致状态。我们绝对可以达到这样的程度,即您拥有一个列名(性别、索引、活动、任何您想要的)和一组与这些列相对应的唯一名称。像这样的:

data_dict = {'gender':
                 {'Male': ['Adam', 'Marc'],
                  'Female': ['Bella']}
             'alive':
                 {'Y': ['Adam', 'Marc'],
                  'N': ['Bella', 'Adam']}
             'index':
                 {1: ['Adam'],
                  2: ['Bella'],
                  3: ['Marc']}
              }

如果这是你想要的,你可以试试这个:

>>> data_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(set)))
>>> for element in input_file_data:
        for key, value in element.items():
            if key != 'name':
                data_dict[key][value].add(element[name])

应该得到你想要的,我想?由于没有您的数据,我无法测试,但请尝试一下。

【讨论】:

  • 感谢您的回答。我的错。我忘了提到我有多个文件,并且并非所有文件都具有相同的标题名称。所以我不能对它们进行硬编码。
  • 不管标题名称如何,如果列的顺序至少相同,您就可以了。我不直接引用任何标题。 idx, name, gender, alive in data 只是从 CSV 中解压缩每一行,并为每个名称分配一个值。实际的列名是什么并不重要。是这个意思吗?
  • 不幸的是,情况并非如此。这些文件可能非常不同。 :( 我目前在脚本中有几个函数,如果没有具有给定标题名称的文件,它将返回一个空文件。
  • 我已经稍微修改了我的答案。让我知道我的假设是否不正确。如果input_file_data 没有一致的状态,我会集中精力修复它,然后再继续处理数据本身。
  • 是的。没有一致的状态。除此之外,所有文件都有一个“名称”列,但并非所有文件都有一个“性别”列。这个脚本不应该只关注性别,而应该适用于任何其他列,如“index”或“alive”或其他任何内容。对不起,这可行吗?
猜你喜欢
  • 2012-10-05
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 2014-11-20
  • 2021-06-06
  • 2021-03-14
  • 2021-05-12
  • 1970-01-01
相关资源
最近更新 更多