我正在使用的数据如下所示:
csv1 = pd.DataFrame({'D': [1-10, 2-10, 3-10, 4-10,...], #dates
...: 'C': [#, #, #, #,...]} #values
csv2 = pd.DataFrame({'D': [3-10, 4-10, 5-10, 6-10,...], #dates
...: 'C': [#, #, #, #,...]} #values
csv3 = pd.DataFrame({'D': [5-10, 6-10, 7-10, 8-10,...], #dates
...: 'C': [#, #, #, #,...]} #values
.
.
.
csv100 = pd.DataFrame({'D': [5-10, 6-10, 7-10, 8-10,...], #dates
...: 'C': [#, #, #, #,...]} #values
我想要一个这样的数据框:
df_merged = pd.DataFrame({'D': [1-10,2-10,3-10,4-10,5-10,6-10...] #dates
...: 'C1': [#, #, #, #, #, #...]} #values
'C2': [#, #, #, #, #, #...]} #values
'C3': [#, #, #, #, #, #...]} #values
.
.
.
'C100': [#, #, #, #, #, #]} #values
我一直在尝试合并多个数据框,大约100个,这些数据框具有相同的列但不同的行(它们没有相同的顺序),我想通过列'date'来进行合并(合并)每一行都有相同的日期)。因为数据帧的数量很高,并且随着时间的推移而变化(今天我可以有110,明天我可以有90 ......),使用循环来合并它们中的每一个的方法太慢了。通过研究解决方案,我发现共识是使用字典。我将此解决方案应用于我的代码,但是我遇到了错误,我不知道如何解决它。代码如下
import pandas as pd
import subprocess
import os
from functools import reduce
path=r'C:\Users\ra\Desktop\Px\a' #Folder 'a' path
df = {} #Dictionary of data frames from csv files in Folder 'a'
x = [#vector that contains the name of the csv file as string]
i = 0
for j in range(len(x)):
df['df%s' %j] = (pd.read_csv(os.path.join(path,r'%s.csv' % x[i]))) #Assigns a key to the data frame Ex.:'df1' (the key is a string and I think this is the problem)
df['df%s' %j].rename(columns={'C': '%s' % x[i]}, inplace=True) #Renames the column 'C' of every data frame to the name of the file
i += 1
df_merged = reduce(lambda left,right: pd.merge(left,right,on=['D'],how='outer'),df) #Merges every data frame to a single data frame 'df_merged' by column 'D' that represents the date.
问题出在最后一行,输出如下:
---> df_merged = reduce(lambda left,right: pd.merge(left,right,on=['D'],how='outer'),df)
.
.
.
ValueError: can not merge DataFrame with instance of type <class 'str'>
如果我将键从字符串更改为整数(通过将向量x更改为简单数字'j'),我得到以下输出:
---> df_merged = reduce(lambda left,right: pd.merge(left,right,on=['D'],how='outer'),df)
.
.
.
ValueError: can not merge DataFrame with instance of type <class 'int'>
为了使代码有效,我试图找到一种将字符串键转换为名称的方法。但是,显然,这是一种罪恶。另外,根据@AnkitMalik,'reduce'方法不能与字典一起使用。如果字典中的键是字符串/整数,如何以pythonic方式通过列'D'合并所有这些数据帧?或者,如果数据框的数量随着时间的推移而变化,如何根据文件夹'a'中的csv文件数量来创建数据框的动态列表?
答案 0 :(得分:1)
合并或追加每个DataFrame非常昂贵,因此尽可能减少通话次数非常重要。
然而,您可以做的是将每个DataFrame的日期列作为DataFrame的索引,将它们放在一个列表中,然后为pandas.concat()
调用所有这些。
你当然必须摆弄列名和它们代表的内容,因为除非你想要一个特定的条目是一个元组,否则你会有一些共同的列。
示例:
>>> import pandas
>>> df_0 = pandas.DataFrame(
{
'a': pandas.date_range('20180101', '20180105'),
'b': range(5, 10)
},
index=range(5)
)
>>> df_0
a b
0 2018-01-01 5
1 2018-01-02 6
2 2018-01-03 7
3 2018-01-04 8
4 2018-01-05 9
>>> df_1 = pandas.DataFrame(
{
'a': pandas.date_range('20180103', '20180107'),
'b': range(5, 10)
},
index=range(5)
)
>>> df_2 = pandas.DataFrame(
{
'a': pandas.date_range('20180105', '20180109'),
'b': range(5, 10)
},
index=range(5)
)
>>> df_0 = df_0.set_index('a')
>>> df_1 = df_1.set_index('a')
>>> df_2 = df_2.set_index('a')
>>> pandas.concat([df_0, df_1, df_2], axis=1) # this is where the magic happens
b b b
a
2018-01-01 5.0 NaN NaN
2018-01-02 6.0 NaN NaN
2018-01-03 7.0 5.0 NaN
2018-01-04 8.0 6.0 NaN
2018-01-05 9.0 7.0 5.0
2018-01-06 NaN 8.0 6.0
2018-01-07 NaN 9.0 7.0
2018-01-08 NaN NaN 8.0
2018-01-09 NaN NaN 9.0
答案 1 :(得分:0)
reduce可以在列表而不是字典上工作。
试试这个:
创建数据框列表(df)
import pandas as pd
import subprocess
import os
from functools import reduce
path='C:\Users\ra\Desktop\Px\a\'
df = []
x = [#vector that contains the name of the csv files as string]
for j in x:
df.append(pd.read_csv(path+j+'.csv'))
df_merged = functools.reduce(lambda left, right: pd.merge(left, right, how= 'outer', on = ['D']), df)
答案 2 :(得分:0)
首先,我要感谢帮助我找到解决方案的每一个人。我不得不说这是我第一次在stackoverflow中发布一个问题并且体验非常好。我还要感谢@AnkitMalik和@NoticeMeSenpai,因为他们的努力帮助我找到了一个非常好的解决方案。
我的问题是使用dictionary {}
合并functools.reduce()
中的数据框。但是,正如@AnkitMalik指出的那样,这只适用于lists []
。 @NoticeMeSenpai建议使用pandas.concat()
来完成这项工作。以下代码适用于我:
import pandas as pd
import subprocess
import os
path='C:\Users\ra\Desktop\Px\a'
df = [] #makes a list of data frames
x = [#vector that contains the name of the csv files as strings]
for j in x:
df.append((pd.read_csv(os.path.join(path,r'%s.csv' % j))).set_index('D').rename(columns={'C':'%s' % j}), axis=1)) #appends every csv file in folder 'a' as a data frame in list 'df', sets the column 'D' as index and renames the column 'C' as the name of csv file.
df_concat = pd.concat(df, axis=1) #concats every data frame in the list 'df'
df_concat.to_csv(os.path.join(path,r'xxx.csv')) # saves the concatenated data frame in the 'xxx' csv file in folder 'a'.