我正在使用Pandas 1.1.2和Python 3.6
我的文件夹中有CV文件,所有文件都具有以下格式(文件中没有标题):
2001-01-01,43,1000
2001-01-02,37,42.5
第一列是日期,其余列是数字。我想遍历文件夹中的所有* .cv文件,然后在数字列中添加所有文件中存在的日期的数字
这是我到目前为止的代码(可能与优化有关):
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?
如何按日期对列进行求和-前提是仅将在所有文件中具有行的日期汇总到汇总结果中?
答案 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()