在Python中统计CSV文件中特定的出现次数
我有一个包含四列的csv文件,分别是{标签(Tag)、用户(User)、质量(Quality)、聚类ID(Cluster_id)}。我想用Python做以下事情:对于每个聚类ID(从1到500),我想查看每个用户的好标签和坏标签的数量(这些信息来自质量这一列)。总共有超过6000个用户。我只能逐行读取这个csv文件,所以我不太确定该怎么做。
举个例子:
Columns of csv = [Tag User Quality Cluster]
Row1= [bag u1 good 1]
Row2 = [ground u2 bad 2]
Row3 = [xxx u1 bad 1]
Row4 = [bbb u2 good 3]
我已经成功获取了csv文件的每一行。
我只能一次访问一行,不能使用两个循环。我想实现的算法的伪代码是:
for cluster in clusters:
for user in users:
if eval == good:
good_num = good_num +1
else:
bad_num = bad_num + 1
2 个回答
3
collections.defaultdict
在这里会非常有用:
# WARNING: Untested
from collections import defaultdict
auto_vivificator = lambda: defaultdict(auto_vivificator)
data = auto_vivificator()
# open your csv file
for tag, user, quality, cluster in csv_file:
user = data[cluster].setdefault(user, defaultdict(int))
if is_good(quality):
user["good"] += 1
else:
user["bad"] += 1
for cluster, users in enumerate(data):
print "Cluster:", cluster
for user, quality_metrics in enumerate(users):
print "User:", user
print quality_metrics
print # A blank line
2
因为已经有人分享了一个使用 defaultdict
的解决方案,所以我想提供一个使用 pandas 的例子,换换口味。pandas
是一个非常实用的数据处理库。它有很多好用的功能,其中之一就是可以用一行代码来解决这个计数问题,具体取决于你需要什么样的输出。真的很简单:
df = pd.read_csv("cluster.csv")
counted = df.groupby(["Cluster_id", "User", "Quality"]).size()
df.to_csv("counted.csv")
--
为了让大家了解 pandas
的简单之处,我们可以加载文件——在 pandas
中,主要的数据存储对象叫做“DataFrame”:
>>> import pandas as pd
>>> df = pd.read_csv("cluster.csv")
>>> df
<class 'pandas.core.frame.DataFrame'>
Int64Index: 500000 entries, 0 to 499999
Data columns:
Tag 500000 non-null values
User 500000 non-null values
Quality 500000 non-null values
Cluster_id 500000 non-null values
dtypes: int64(1), object(3)
我们可以检查一下前几行数据是否正常:
>>> df[:5]
Tag User Quality Cluster_id
0 bbb u001 bad 39
1 bbb u002 bad 36
2 bag u003 good 11
3 bag u004 good 9
4 bag u005 bad 26
然后我们可以按 Cluster_id 和 User 进行分组,并对每个组进行操作:
>>> for name, group in df.groupby(["Cluster_id", "User"]):
... print 'group name:', name
... print 'group rows:'
... print group
... print 'counts of Quality values:'
... print group["Quality"].value_counts()
... raw_input()
...
group name: (1, 'u003')
group rows:
Tag User Quality Cluster_id
372002 xxx u003 bad 1
counts of Quality values:
bad 1
group name: (1, 'u004')
group rows:
Tag User Quality Cluster_id
126003 ground u004 bad 1
348003 ground u004 good 1
counts of Quality values:
good 1
bad 1
group name: (1, 'u005')
group rows:
Tag User Quality Cluster_id
42004 ground u005 bad 1
258004 ground u005 bad 1
390004 ground u005 bad 1
counts of Quality values:
bad 3
[etc.]
如果你打算处理很多 csv
文件,真的值得一看。