我有一个csv文件,如下所示
year,gender,age,country
2002,F,9-10,CO
2002,F,9-10,CO
2002,M,9-10,CO
2002,F,9-10,BR
2002,M,11-15,BR
2002,F,11-15,CO
2003,F,9-10,CO
2003,M,9-10,CO
2003,F,9-10,BR
2003,M,9-10,CO
2004,F,11-15,BR
2004,F,11-15,CO
2004,F,9-10,BR
2004,F,9-10,CO
我想得到这样一个输出文件:
year,gender,age,country,population
2002,F,9-10,CO,2
2002,M,9-10,CO,1
2002,F,9-10,BR,1
2002,M,9-10,BR,0
2002,F,11-15,CO,1
2002,M,11-15,CO,0
2002,F,11-15,BR,0
2002,M,11-15,BR,1
2003,F,9-10,CO,1
2003,M,9-10,CO,1
2003,F,9-10,BR,1
2003,M,9-10,BR,0
2003,F,11-15,CO,0
2003,M,11-15,CO,0
2004,F,9-10,CO,1
2004,M,9-10,CO,0
2004,F,9-10,BR,1
2004,M,9-10,BR,0
2004,F,11-15,CO,1
2004,M,11-15,CO,0
2004,F,11-15,BR,1
2004,M,11-15,BR,0
基本上,我想打印出每一年,每个年龄,每个国家的女性人数,所以年份,性别,年龄和国家将是字典的关键。此外,有些年份没有特定国家的数据,有些年份没有特定国家的特定年龄。例如,2003年,在CO国家,妇女没有关于11-15岁年龄组的数据。在这种情况下,人口将为0。此外,有些年份根本没有具体的性别数据。例如,在2004年,没有所有年龄和国家的男性数据,但我仍然希望在人口为0的输出文件中打印出来。
下面是我编写的一些python代码,但它不起作用,我不知道如何处理丢失的数据,并将其打印为0。
import csv
import os
import sys
from operator import itemgetter, attrgetter
import math
from collections import Counter
# Create dictionary to hold the data
valDic = {}
# Read data into dictionary
with open(sys.argv[1], "r",) as inputfile:
readcsv = csv.reader(inputfile, delimiter = ',')
next(readcsv)
for line in readcsv:
key = line[0] + line[1] + line[2] + line[3]
year = line[0]
gender = line[1]
age = line[2]
country = line[3]
if key in valDic:
key = key + 1
else:
valDic[key] = [year, gender, age, country, 0] # 0s are placeholder for running sum and itemCount
inputfile.close()
newcsvfile = []
for key in valDic:
newcsvfile.append([valDic[key][0], valDic[key][1], valDic[key][2], valDic[key][3], len(valDic[key])])
newcsvfile = sorted(newcsvfile)
newcsvfile = [["year", "gender", "age", "country", "population"]]
with open(sys.argv[2], "w") as outputfile:
writer = csv.writer(outputfile)
writer.writerows(newcsvfile)
发布于 2019-10-30 18:33:05
我们可以以元组的形式存储年份、性别、年龄、国家的每一个组合,并以此作为词典的关键。我们还维护这些值的唯一集合。我们重复我们看到的每一个组合,如果数据不存在(就像2004年只有女性存在,而不是男性),那么我们可以为这个添加'0‘。
演示:
import csv
import sys
# Create dictionary to hold the data
valDic = {}
years, genders, age, country = set(), set(), set(), set()
# Read data into dictionary
with open(sys.argv[1], 'r',) as inputfile:
reader = csv.reader(inputfile, delimiter = ',')
next(reader)
for row in reader:
key = (row[0], row[1], row[2], row[3])
years.add(key[0])
genders.add(key[1])
age.add(key[2])
country.add(key[3])
if key not in valDic:
valDic[key]=0
valDic[key]+=1
#Add missing combinations
for y in years:
for g in genders:
for a in age:
for c in country:
key = (y, g, a, c)
if key not in valDic:
valDic[key]=0
#Prepare new CSV
newcsvfile = [["year", "gender", "age", "country", "population"]]
for key, val in sorted(valDic.items()):
newcsvfile.append([key[0], key[1], key[2], key[3], valDic[key]])
with open(sys.argv[2], "w", newline='') as outputfile:
writer = csv.writer(outputfile)
writer.writerows(newcsvfile)
产出:
year,gender,age,country,population
2002,F,11-15,BR,0
2002,F,11-15,CO,1
2002,F,9-10,BR,1
2002,F,9-10,CO,2
2002,M,11-15,BR,1
2002,M,11-15,CO,0
2002,M,9-10,BR,0
2002,M,9-10,CO,1
2003,F,11-15,BR,0
2003,F,11-15,CO,0
2003,F,9-10,BR,1
2003,F,9-10,CO,1
2003,M,11-15,BR,0
2003,M,11-15,CO,0
2003,M,9-10,BR,0
2003,M,9-10,CO,2
2004,F,11-15,BR,1
2004,F,11-15,CO,1
2004,F,9-10,BR,1
2004,F,9-10,CO,1
2004,M,11-15,BR,0
2004,M,11-15,CO,0
2004,M,9-10,BR,0
2004,M,9-10,CO,0
发布于 2019-10-30 20:10:00
为此,我将使用pandas
。
我可以全部阅读并创建DataFrame
import pandas as pd
df = pd.read_csv(sys.argv[1])
使用groupby
,我可以对行进行分组并对它们进行计数,以获得现有数据的population
。它创建具有不同顺序的列的列表,但稍后我将将其转换为新的DataFrame
,以更改列的顺序和行的排序。
groups = df.groupby(['year', 'age', 'country', 'gender'])
data = []
for index, group in groups:
data.append([*index, len(group)]) # create row with population
.unique()
我可以在列中获得所有唯一的值。
unique_years = df['year'].unique()
unique_genders = df['gender'].unique()
unique_age = df['age'].unique()
unique_countries = df['country'].unique()
我使用它们与itertools.product
一起创建所有可能的年份、性别、年龄、国家组合,以检查数据中缺少哪一个组合,以将其与0
相加。
现有的组合,我可以找到以前的groups.indices
import itertools
all_indices = groups.indices
for index in itertools.product(all_years, all_age, all_countries, all_genders):
if index not in indices:
data.append([*index, 0]) # add missing row
之后,我拥有了所有的数据,我可以转换为DataFrame
来更改列、顺序和排序行。
# create DataFrame with new values
final_df = pd.DataFrame(data, columns=['year', 'age', 'country', 'gender', 'population'])
# change columns order
final_df = final_df[['year', 'gender', 'age', 'country', 'population']]
# sort by
final_df = final_df.sort_values(['year', 'age', 'country', 'gender'], ascending=[True, False, False, True])
最后,我可以将它保存在新的csv中。
final_df.to_csv(sys.argv[2], index=False)
完整的示例--而不是从文件中读取--我使用io.StringIO
来模拟内存中的文件,这样每个人都可以在没有完整数据的情况下复制和测试它。
text = '''year,gender,age,country
2002,F,9-10,CO
2002,F,9-10,CO
2002,M,9-10,CO
2002,F,9-10,BR
2002,M,11-15,BR
2002,F,11-15,CO
2003,F,9-10,CO
2003,M,9-10,CO
2003,F,9-10,BR
2003,M,9-10,CO
2004,F,11-15,BR
2004,F,11-15,CO
2004,F,9-10,BR
2004,F,9-10,CO'''
#---------------------------------------
import pandas as pd
#df = pd.read_csv(sys.argv[1])
import io
df = pd.read_csv(io.StringIO(text))
print(df)
#---------------------------------------
groups = df.groupby(['year', 'age', 'country', 'gender'])
data = []
for index, group in groups:
data.append([*index, len(group)])
#---------------------------------------
unique_years = df['year'].unique()
unique_genders = df['gender'].unique()
unique_age = df['age'].unique()
unique_countries = df['country'].unique()
#print('years :', unique_years)
#print('genders :', unique_genders)
#print('age :', unique_age)
#print('countries:', unique_countries)
import itertools
all_indices = groups.indices
for index in itertools.product(all_years, all_age, all_countries, all_genders):
if index not in indices:
data.append([*index, 0])
#---------------------------------------
# create DataFrame with new values
final_df = pd.DataFrame(data, columns=['year', 'age', 'country', 'gender', 'population'])
# change columns order
final_df = final_df[['year', 'gender', 'age', 'country', 'population']]
# sort by
final_df = final_df.sort_values(['year', 'age', 'country', 'gender'], ascending=[True, False, False, True])
# reset index
final_df = final_df.reset_index(drop=True)
print(final_df)
# save in file
#final_df.to_csv(sys.argv[2], index=False)
final_df.to_csv('output.csv', index=False)
https://stackoverflow.com/questions/58631387
复制相似问题