【问题标题】:Read a .csv file and join values based on equal values in specific column读取 .csv 文件并根据特定列中的相等值连接值
【发布时间】:2018-05-31 08:06:02
【问题描述】:

我有一个 csv 文件,它包含三列(A、B 和 C),它们的值如下图所示: CSV Table

1,2,4
1,257,5
1,258,6
1,8,7
1,260,8
2,24,9
2,26,10
2,234,11
3,14,12
3,22,13
3,78,14

我想通过 "-" 加入 B 列中的值,而它们在 A 列中的值相同。因此,预期的输出如下:

[“2-257-258-8-260”、“24-26-234”、“14-22-78”]

谁能帮助我如何获得这些结果。

提前致谢

【问题讨论】:

  • 发布可测试的输入片段,不要将输入发布为图像
  • 如果您将该示例数据作为文本包含在您的问题中,人们会更容易为您提供帮助。从图像中复制数据并不容易。请参阅Why may I not upload images of code on SO when asking a question?。您还应该发布自己为该任务编写代码的尝试,清楚地说明您遇到的困难。
  • 您的输出并不暗示您所描述的任何逻辑
  • 我了解您想要做什么,但是 A 列中的值会始终组合在一起吗?它们是否总是按升序排序?
  • @Mohammad 请试试我的回答

标签: python list csv


【解决方案1】:

如果您的数据集采用以下格式:

A,B,C
1,2,4
1,257,5
1,258,6
1,8,7
1,260,8
2,24,9
2,26,10
2,234,11
3,14,12
3,22,13
3,78,14

您可以使用itertools.groupby()A 列中的项目进行分组,并连接B 列中的元素:

from csv import reader
from itertools import groupby
from operator import itemgetter

with open('data.csv') as in_file:
    csv_reader = reader(in_file)

    # skip headers
    next(csv_reader)

    # sort data by A column, then C column
    sorted_data = sorted(csv_reader, key=itemgetter(0, 2))

    # group by A column, and join by B column
    grouped = ['-'.join(map(itemgetter(1), g)) for _, g in groupby(sorted_data, key=itemgetter(0))]
    print(grouped)

哪些输出:

['2-257-258-8-260', '24-26-234', '14-22-78']

注意:此解决方案在分组之前排序,以防数据尚未主要在列A 上排序,然后在列C 上排序。

【讨论】:

  • FWIW,我也想过使用groupby,但我不想对数据进行排序,并且 OP 没有回答我关于它总是被排序的问题。顺便说一句,很好地使用itemgetter。我讨厌人们在lambda 上使用map
  • @PM2Ring 是的,我认为事先排序不会有问题。当然,如果始终对数据进行排序,此解决方案仍然有效,这只是一种安全措施。我个人更喜欢你的defaultdict 方法。
  • 顺便说一句,您可以将排序键功能设为itemgetter(0, 2),以便将A列作为主键和C列作为辅助键对项目进行排序。
【解决方案2】:

这是一个简单的 Python 解决方案。

我们使用csv 阅读器来读取数据。在我的代码中,我从名为file_data 的行列表中读取,但您可以将file_data 更改为打开的文件对象。

我们将数据存储到一个列表字典中,A 列的值作为键,B 列的值被附加到一个列表中。

然后我们按顺序遍历键,将 B 数据连接成所需形式的字符串。

import csv
from collections import defaultdict

file_data = '''\
1,2,4
1,257,5
1,258,6
1,8,7
1,260,8
2,24,9
2,26,10
2,234,11
3,14,12
3,22,13
3,78,14
'''.splitlines()

reader = csv.reader(file_data)
data = defaultdict(list)
for a, b, c in reader:
    #print(a, b, c)
    data[a].append(b)

out = ['-'.join(data[k]) for k in sorted(data.keys())]
print(out)

输出

['2-257-258-8-260', '24-26-234', '14-22-78']

【讨论】:

  • 感谢所有答案,但这段代码在其他答案中为我提供了大型数据集的最佳时间性能,谢谢老兄:)
【解决方案3】:

熊猫解决方案

尝试使用 pandas groupby 函数,然后使用 pandas apply,然后在其中写入 lambda x:,然后使用 '-' 加入新的列表理解:

import pandas as pd
df = pd.DataFrame({'A':[1,1,1,2,2,3,3], 'B': [124,456,465,46,35,53,33]})
print(df.groupby('A')['B'].apply(lambda x: '-'.join([str(i) for i in x.values])).tolist())

输出:

['124-456-465', '46-35', '53-33']

【讨论】:

  • 是什么让你认为 OP 有 Pandas?使用标准的csv 模块和defaultdict,甚至是普通的dict,可以轻松完成此任务。
  • @PM2Ring 哦,是的,那么我将添加一个常规的 python 方式
  • @PM2Ring 我认为你的答案是最有效的常规 python 搜索
猜你喜欢
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 2013-06-18
相关资源
最近更新 更多