我有12个csv文件,其中包含每个月的工资数据。命名约定为YYYYMMDD。例如,1月份的工资数据存储在名为20200131的csv文件中。我想读取所有csv文件,并将所有员工的工资数据合并到一个csv文件中。每列的标题应为Sal_Jan、Sal_Feb等,而所有csv文件中的员工名称应仅使用一次。
20200131.csv中存储的一月数据为:
姓名 | |
---|---|
A | 20000 |
B | 25000 |
所以试试这个。这对我来说很有效。我用你指定的文件名创建了csv文件,输出如我所示打印出来。这应该是带注释的完整解决方案。如果你还有其他问题,一定要问。
import pandas as pd
import calendar as cl
import glob
path = r'C:/Users/Akshay/Documents/Question 2'
all_files = glob.glob(path + "/*.csv")
# Need to sort the files so that the columns are in order from Month 1 -> 12
all_files.sort()
# The following function converts the month number to "Sal_Jan",
# "Sal_Feb", etc. The index -8 to -6 is the position in the file
# name where the month number shows up.
#
def f(fn): return str("Sal_" + cl.month_abbr[int(fn[-8:-6])])
li = []
# The first column in the data frame will be the "Name" column.
# The usecols method is saying to get the 0-th column
li.append(pd.read_csv(all_files[0], index_col=None, header=0, usecols=[0]))
for filename in all_files:
# As each file is accessed, it is only appending the salary data
# and is converting the month column name to the specified one
df = pd.read_csv(filename, usecols=[1], header=0, names=[f(filename)])
li.append(df)
# Specified the Name column as an index, so that the 0,1,2 index is removed.
frame = pd.concat(li, axis=1).set_index('Name')
print(frame)
因此,在格式化csv文件并填充一些数据之后,输出就是这样出现的:
Sal_Jan Sal_Feb Sal_Mar Sal_Apr Sal_May Sal_Jun
Name
A 20000 30000 30255 30510 30765 31020
B 21000 31000 31255 31510 31765 32020
C 22000 32000 32255 32510 32765 33020
D 24000 34000 34255 34510 34765 35020
E 28000 38000 38255 38510 38765 39020
F 10000 20000 20255 20510 20765 21020
G 11000 21000 21255 21510 21765 22020
H 14000 24000 24255 24510 24765 25020
I 13000 23000 23255 23510 23765 24020
J 22500 32500 32755 33010 33265 33520
K 23500 33500 33755 34010 34265 34520
请注意,列标题和数据之间的额外行不是额外的行(即不是NULL行(。它以这种方式打印在控制台中;名称";列是一个索引。
编辑:所以我刚刚注意到你提供了样本文件,所以我用你的样本文件重新运行了我的代码,这就是输出:
Sal_Jan Sal_Feb Sal_Mar Sal_Apr Sal_May Sal_Jun Sal_Jul Sal_Aug Sal_Sep Sal_Oct
Name
A 10000 15000 20000 25000 30000 35000 40000 45000 50000 55000
B 10000 15000 20000 25000 30000 35000 40000 45000 50000 55000
C 10000 15000 20000 25000 30000 35000 40000 45000 50000 55000
尝试使用functools
中的reduce
合并数据帧。
#import package
import pandas as pd
from functools import reduce
#reproducing your dataframe images...
df1 = pd.DataFrame({"Name" : ["A","B"],
"Salary" : [20000,25000]})
df2 = pd.DataFrame({"Name" : ["A","B"],
"Salary" : [21000,26000]})
#Create a list of all dfs
dfs = [df1, df2,]
#merge on name
df3 = reduce(lambda left,right: pd.merge(left,right,on='Name'), dfs)
#rename the columns
df3.columns = ['Name', 'Sal_Jan', 'Sal_Feb']
仅重命名特定列的替代方法:
df3 = df3.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
我认为您不需要concat,而是需要合并数据帧。如果你认为每个月都有不同的员工,最好的选择是完全外部加入数据帧。
命令如下:
pd.merge(first_pd,second_pd,on='Name',how='outer')
如果你的数据帧总是有一列引用名为";名称">outer意味着,如果员工姓名与任何数据帧不匹配,其位置将被替换为NaN
您可以按照以下要点浏览整个解决方案:https://gist.github.com/irongraft/c12895419fa241adc03ec0635e45aebe
ciao
试试这个简单的解决方案:
import os
import panda as pd
directory = r'SalaryFilesDirectoryPath'
dfresult=pd.DataFrame({})
for filename in os.listdir(directory):
df=pd.read_csv(filename)
dfresult['Name']=df['Name']
dfresult[filename[8:-4]]=df['Salary']
dfresult.to_csv('outputname.csv')
附言:只有当你按字母顺序命名每个csv时,这才会起作用,否则,你会有未排序的月份+文件夹必须只包含csv工资文件+如果你在每个csv中有不同的名称,你需要升级它。