首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果键是字符串/整数,则合并字典中的多个pandas数据帧

如果键是字符串/整数,则合并字典中的多个pandas数据帧
EN

Stack Overflow用户
提问于 2018-03-01 08:27:12
回答 3查看 4.9K关注 0票数 0

我使用的数据如下所示:

代码语言:javascript
运行
复制
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

我想要一个这样的数据框:

代码语言:javascript
运行
复制
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个,这些数据框具有相同的列但不同的行(它们没有相同的顺序),我想按“日期”列进行合并(合并具有相同日期的每一行)。因为数据帧的数量很大,并且随着时间的推移而变化(今天我可能有110个,明天我可能有90个…),使用循环合并每个数据帧的方法太慢了。通过研究解决方案,我发现大家的共识是使用字典。我将这个解决方案应用到我的代码中,但我得到了一个错误,我不知道如何解决它。代码如下所示

代码语言:javascript
运行
复制
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.

问题出在最后一行,输出如下:

代码语言:javascript
运行
复制
---> 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'>

如果我将key从字符串更改为整数(通过将向量x更改为简单数字'j'),我会得到以下输出:

代码语言:javascript
运行
复制
---> 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文件的数量变化,我如何创建数据帧的动态列表?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-03-01 23:42:05

首先,我要感谢每一个帮助我找到解决方案的人。我不得不说,这是我第一次在stackoverflow上发布问题,体验非常好。我还要感谢@AnkitMalik和@NoticeMeSenpai,因为他们的努力帮助我找到了一个非常好的解决方案。

我的问题是关于使用functools.reduce()dictionary {}中合并数据帧。但是,正如@AnkitMalik指出的那样,这只适用于lists []。@NoticeMeSenpai推荐使用pandas.concat()来实现这一点。下面的代码适用于我:

代码语言:javascript
运行
复制
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'.
票数 0
EN

Stack Overflow用户

发布于 2018-03-01 10:43:20

合并或附加每个DataFrame的开销非常大,因此尽可能少地调用是很重要的。

但是,您可以做的是将每个DataFrame的date列作为DataFrame的索引,将它们放在一个列表中,然后为所有它们调用一次pandas.concat()

当然,您必须处理列名及其表示的内容,因为除非您希望某个特定条目是一个元组,否则您将拥有一些公共列。

示例:

代码语言:javascript
运行
复制
>>> 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
EN

Stack Overflow用户

发布于 2018-03-01 09:00:58

reduce将在列表而不是字典上工作。

试试这个:

创建数据帧列表(df)

代码语言:javascript
运行
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49040837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档