【问题标题】:Pandas sum columns on matching dates in multiple csv filesPandas 对多个 csv 文件中匹配日期的列求和
【发布时间】:2020-09-15 11:00:54
【问题描述】:

我正在使用 Pandas 1.1.2 和 Python 3.6

我的文件夹中有 CV 文件,格式如下(文件中没有标题):

sample.csv

2001-01-01,43,1000
2001-01-02,37,42.5

第一列是日期,其余列是数字。我想全局化文件夹中的所有 *.cv 文件,并在数字列中添加数字所有文件中存在的日期

这是我到目前为止的代码(可能与优化有关):

example.py

from pathlib import Path
from datetime import datetime as dt
import pandas as pd

ROOT_DIR='/some/path'
DATA_COL_DATE = 'dt'
COL_NAMES = ('dt','weight','age')

dates = []

# First get all dates available
pathlist = Path(ROOT_DIR).glob('**/*.csv')
for filename in pathlist:
     # because filename is object not string
     with open (str(filename), 'r') as f:
         temp = list(set([dt.strptime(x[0], DATE_FORMAT) for x in f.readlines()]))
         dates.extend(temp)

dates.sort()

# Second pass :/
for filename in pathlist:
     # because filename is object not string
     df = pd.read_csv(str(filename), names=COL_NAMES, header=None, parse_dates=parse_dates)
        df2 = df.set_index(df[DATA_COL_DATE])
        df2.sort_index(inplace=True) 

# ... now what?

如何按日期对列求和 - 条件是只有在 ALL FILES 中有行的日期才会在聚合结果中求和?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我认为我们可以使用 pandas 和 pathlib 稍微整理一下:

    import pandas as pd 
    from pathlib import Path 
        
            
    def gather_files(root_dir):
        if not Path(root_dir).is_dir():
            raise FileNotFoundError('Directory is not valid!')
        return [file for file in Path(root_dir).glob('*.csv')]
    
    
    def return_summed_dataframe(list_of_csv_paths):
        dfs = pd.concat(
                     [pd.read_csv(file,parse_dates='dt').assign(src=file.stem) 
                     for file in list_of_csv_paths]
                    )
    
        de_duped_df = dfs[dfs.duplicated(subset='dt',keep=False)]
    
        de_duped_df = de_duped_df[de_duped_df.groupby('dt')['src'].transform('size')\
                                                  .ge(len(list_of_csv_paths))]
    
        return de_duped_df.groupby('dt').sum()
    

    用法。

    files = gather_files('path/to/files')
    
    df = return_summed_dataframe(files)
    
    df.to_csv(...)
    

    这里的关键是 duplicated()keep=False,这将返回所有重复值 - 这意味着日期至少必须存在于 +1 源文件中。

    其次,我们可以在src 列上执行size(),以测试每个唯一日期是否至少大于我们文件的长度。 (文件可能有重复的日期,因此大小可能大于文件的长度)

    以这个df为例。

      src        date
    0   A  01-01-2020
    1   A  01-01-2020
    2   B  01-01-2020
    3   B  01-03-2020
    4   C  01-01-2020
    5   C  01-03-2020
    

    首先我们按日期查找重复项,暂时忽略 src。

    src = ['A','B','C']
    df1 = df[df.duplicated(subset='date',keep=False)]
    
    print(df1)
    
      src        date
    0   A  01-01-2020
    1   A  01-01-2020
    2   B  01-01-2020
    3   B  01-03-2020
    4   C  01-01-2020
    5   C  01-03-2020
    

    #if you have duplicate dates in each file we can do an initial groupby
    # df1.groupby('date').agg(size=('size','sum),weight=('weight','sum'),
    #                         src=('src','first')
    final = df1[df1.groupby('date')['src'].transform('size').ge(len(src))]
    
    
    print(final)
    
      src        date
    0   A  01-01-2020
    1   A  01-01-2020
    2   B  01-01-2020
    4   C  01-01-2020
    

    【讨论】:

    • @ShubhamSharma 谢谢,这是一个有趣的问题,但我只是想到了一个错误,如果A 的重复日期与文件数量一样多或更多,那么该日期将被过滤掉跨度>
    • 是的,这很有趣! IMO文件不应该有欺骗性,否则OP会在问题中说明..另一方面,如果有重复的日期,那么恕我直言,我们可以在这些日期首先groupby并使用sum聚合每个数据框:)
    • @ShubhamSharma 你是对的,每个 CSV 文件中的日期都是唯一的。
    • 感谢您的详细回答和描述。
    【解决方案2】:

    让我们创建一个partial func 来读取索引设置为date 列的csv 文件,然后使用reduce 和缩减函数DataFrame.add 添加所有csv 文件,最后使用dropna 删除具有NaN 值的行:

    from functools import reduce, partial
    
    f = partial(pd.read_csv, header=None, names=COL_NAMES, index_col=0)
    df = reduce(pd.DataFrame.add, [f(path) for path in pathlist]).dropna()
    

    【讨论】:

    • 我喜欢这个,因为它很简洁,但与此同时,我不确定我是否完全理解它(即它没有一些会在后面咬我的陷阱) .在我接受答案之前,我必须对其进行全面测试——尽管它在美学上非常令人愉悦! :)
    • 一定要花时间去测试 :)
    猜你喜欢
    • 2018-03-03
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    • 2021-02-15
    • 2018-12-14
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    相关资源
    最近更新 更多