【问题标题】:Append to a list of dataframes with correct object type附加到具有正确对象类型的数据框列表
【发布时间】:2020-09-27 04:10:30
【问题描述】:

我猜这个问题并非特定于熊猫。 我试图在一个文件夹中找到所有 xls 文件,用 pandas 读取它们并将它们中的每一个写入数据框。之后我想将所有数据帧连接到一个。

在循环中,我使用此命令重命名每个数据帧并带有日期戳(以便保留它以供以后连接):

exec("%s = %s" % ('data_'+date,'data'))

然后将新的数据框名称附加到列表中:

dataframes = dataframes + 'data_'+date

当我尝试通过以下方式连接此列表时:

data_total = pd.concat(dataframes)

我不断收到错误:

TypeError: cannot concatenate object of type '<class 'str'>'; only Series and DataFrame objs are valid

我知道制作字符串列表是行不通的,我应该建立一个数据框列表。我该怎么做呢?当我手头没有明确的变量名时,我很难理解如何进行分配。

更新: 我发布了更多代码以便更好地理解。

# filepaths is a list of paths to excel files in the folder

dataframes = []
for file in filepaths:
    date = file[-14:-4]                              # Read date from file name
    data = pd.read_excel(file)                       # Read excel sheet
    exec("%s = %s" % ('data_'+date,'data'))          # rename data frame
    dataframes = dataframes + 'data_'+date           # Update list of data frames for concatenation below

data_total = pd.concat(dataframes)

谢谢, 塞巴斯蒂安

【问题讨论】:

  • 欢迎堆栈溢出!请以minimal reproducible example 的形式发布您的所有代码,我们可以执行或至少直接阅读。还包括完整的traceback,因为这对调试很有帮助。谢谢!
  • 感谢您的建议。我添加了一个瘦身版。
  • 您必须将data(的副本)添加到数据帧,而不是字符串'data_'+date
  • 谢谢卢伊克。我正在通过重命名来制作副本。然后您将如何将此副本添加到列表中?

标签: python pandas


【解决方案1】:

动态变量名是一种反模式。它给了程序员一堆几乎无法访问的对象。如果要将名称关联到对象,正确的方法是使用字典:

dataframes = {}
for file in filepaths:
    date = file[-14:-4]                              # Read date from file name
    data = pd.read_excel(file)                       # Read excel sheet
    dataframes[date] = data                          # store the dataframe with its date

data_total = pd.concat(dataframes.values())

但是这里你没有使用名字,所以你可以使用一个简单的列表:

dataframes = []
for file in filepaths:
    data = pd.read_excel(file)                       # Read excel sheet
    dataframes.append(data)                          # store the dataframe

data_total = pd.concat(dataframes)

或者理解:

data_total = pd.concat([pd.read_excel(file) for file in filepaths])

【讨论】:

  • 您的第二个建议解决了它。但是,dataframes[date] = data 不起作用,因为索引必须是整数,而不是字符串。非常感谢!
  • @zip 您的评论表明您没有复制第一个示例 逐字 并将dataframes 创建为列表而不是字典。列表使用索引(整数)来查找它们的值,而字典使用键(唯一的、可散列的值,例如字符串)来查找它们的值。
  • 感谢@HampusLarsson,感谢您的回答。
【解决方案2】:

解决方案

您不需要单独命名数据框。据我了解,您希望将不同的数据框连接起来(沿axis=0),并为每个数据框添加一个具有相应日期的列。 date 是从 excel 文件的名称中提取出来的,并添加到最终数据框中的 date 列中。

下面的解决方案首先使用glob 库来获取.xlsx (excel) 文件的列表。然后它使用list-comprehension 将所有数据帧组合在一起,同时动态读取每个数据帧并使用pandas.Dataframe.assign()lambda-function 添加date 列。

import pandas as pd
from glob import glob

base_path = 'some_directory'
excel_files = glob(base_path + '/*.xlsx')

## Read all the excel files and store 
#  in a list of dataframes: dfs
#  >>> dfs --> dataframes
dfs = [(pd.read_excel(excel_file))
          .assign(date=excel_file[-14:4]) \
       for excel_file in excel_files]
## Consolidate all dataframes
#  >>> data_total --> consolidated dataframe
df = pd.concat(dfs, axis=0) 

一行中的完整解决方案

import pandas as pd
from glob import glob

base_path = 'some_directory'
df = pd.concat([( pd.read_excel(excel_file))
                    .assign(date=excel_file[-14:4] ) \
        for excel_file in glob(base_path + f'/*.xlsx')], 
        axis=0)

我建议您不要使用变量名称data_total,因为它会错误地给人以数据总和(总和值)的印象。如果我没记错的话,您想要的是所有数据框的合并数据框。

在最终数据框中不保存日期的解决方案

import pandas as pd
from glob import glob

base_path = 'some_directory'
excel_files = glob(base_path + f'/*.xlsx')
df = pd.concat([pd.read_excel(excel_file) for excel_file in exce_files], axis=0)

【讨论】:

  • @zip 我希望这会有所帮助。请尝试一下,如果您有任何问题,请告诉我。
  • 我实际上只是使用日期来为各个数据框命名 - 而不是向数据框添加列。由于不再需要它(因为我以后不需要单独的数据帧),解决方案变得更加简单。非常感谢!
  • @zip 如果您不需要date 列,只需删除.assign(...) 部分以避免额外的处理。
猜你喜欢
  • 2023-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 2021-12-10
  • 2021-07-12
相关资源
最近更新 更多