熊猫对多个csv文件中匹配日期的列进行汇总

时间:2020-09-15 11:00:54

标签: python pandas dataframe

我正在使用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?

如何按日期对列进行求和-前提是仅将在所有文件中具有行的日期汇总到汇总结果中?

2 个答案:

答案 0 :(得分:3)

我认为我们可以使用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源文件中。

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

以这个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

答案 1 :(得分:2)

让我们创建一个partial函数,以读取索引设置为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()