Python 将字典中的值打印到新的csv文件

Python 将字典中的值打印到新的csv文件,python,pandas,numpy,data-cleaning,Python,Pandas,Numpy,Data Cleaning,我有一个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-1

我有一个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年,女性没有country CO中11-15岁年龄组的数据。在这种情况下,人口将为0。此外,有些年份根本没有具体的性别数据。例如,对于2004年,没有所有年龄和国家的男性数据,但我仍然希望将其打印在人口为0的输出文件中

下面是我编写的一些python代码,但它不起作用,我不知道如何处理丢失的数据,并在population字段中将其打印为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)        

我们可以将年份、性别、年龄、国家的每个组合存储为一个元组,并将其用作字典的键。我们还维护每个值的唯一集合。我们反复研究我们所看到的每一个组合,如果没有相关数据(比如2004年,只有女性存在,但没有男性);然后我们可以为此添加“0”

演示:

导入csv
导入系统
#创建字典来保存数据
valDic={}
年,性别,年龄,国家=set(),set(),set(),set()
#把数据读入字典
打开(sys.argv[1],'r',)作为输入文件:
reader=csv.reader(输入文件,分隔符=',')
下一位(读者)
对于读取器中的行:
键=(第[0]行、第[1]行、第[2]行、第[3]行)
年份。添加(键[0])
性别。添加(键[1])
添加年龄(键[2])
country.add(键[3])
如果钥匙不在valDic中:
valDic[键]=0
valDic[键]+=1
#添加缺少的组合
对于y年:
就性别而言:
对于一个年轻人:
对于国内的c:
键=(y,g,a,c)
如果钥匙不在valDic中:
valDic[键]=0
#准备新的CSV
newcsvfile=[[“年”、“性别”、“年龄”、“国家”、“人口”]]
对于键,val已排序(valDic.items()):
newcsvfile.append([key[0],key[1],key[2],key[3],valDic[key]]))
将open(sys.argv[2],“w”,换行=”)作为输出文件:
writer=csv.writer(输出文件)
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

我会用熊猫来做这个

我可以读取所有内容并创建
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
Usign
.unique()
我可以在列中获取所有唯一值

unique_years     = df['year'].unique()
unique_genders   = df['gender'].unique()
unique_age       = df['age'].unique()
unique_countries = df['country'].unique()
我将它们与
itertools.product
一起使用,创建年份、性别、年龄、国家/地区的所有可能组合,以检查数据中缺少的组合,并将其添加到
0

我可以找到以前的
组。索引的现有组合

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)

使用
df.groupby(['year'、'genter'、'age'、'country'])
您可以计算它。您可以在开始时创建包含所有键和值的字典0。如果csv中不存在某个键,则字典中将有0。@furas您可以更具体地说明如何执行该操作吗?在真实的文件中有两个以上的国家和年龄段,我不能全部列出。我对编码还不熟悉,所以我不知道如何创建一个包含所有键的dic,正如您所说,要获得0的缺失值,您必须首先创建包含所有国家/地区、所有年龄段的列表。使用这些列表,您可以在填充字典后检查字典中是否缺少数据。或者在开始时,您可以创建字典,其中所有项都由零填充,然后从csv中添加值。所以,您必须首先只读取csv以获取所有国家和所有年龄范围,然后再次读取csv以创建字典。