对于跨多个文件夹循环以在多个CSV文件中重新采样日期时间并使用自动生成的文件名导出

时间:2016-11-22 10:02:26

标签: python csv datetime export-to-csv

我的计算机上的文档中有多个数据框(csv文件)位于各种文件夹中。所有csv文件具有相同的列数,其中每列的名称相同且顺序相同,但是,文件中存在不同数量的数据行。所有文件都有"日期时间"作为他们的第一栏,其中" YYYYMMDD HH:MM:SS"记录下来的数据行。

我想重新采样所有数据框,以便从原始文件创建每小时,每日和每月数据。 csv文件中的某些列要求数据在小时,日和月中求和,而其他列需要在这些时间帧上对数据求平均值(在所有csv文件中保持一致)。我希望每个原始csv文件都有自己的每小时,每日和每月版本。

所有csv文件都存在于以下inputpath中,但实际上位于此inputpath中的其他文件中:

inputpath =' C:/ Users / cp_vm / Documents / Data / Input / Clean /'

例如,在文件夹" Clean"还有两个文件夹,其中包含所有csv文件。我想读取所有存在于" Clean"之后的csv文件。文件夹,无需编写多个输入路径'并如前所述重新取样文件。

然后,我想将这些重新采样的数据框导出到它们来自的文件夹,并添加"小时","日"或"月"他们的名字。

下面提供了csv文件的代码段示例。

enter image description here

例如,我想将15分钟间隔数据重新采样为每小时,每日和每月数据。重采样时需要对前两列求和,而第三列需要在重采样时间帧上求平均值。我知道df.resample(' h')。sum()将对小时内的数据求和,而.mean()将平均一小时内的数据,但是当不同列需要不同时,它很棘手重新采样,然后想要将所有这些列组合在一起,然后将每小时,每日或每月文件导出到文件名已自动更改的相应位置,以显示它现在是每小时,每天或每月。

我意识到这是非常具有描述性的,但它导致了各种延迟并重新定位csv文件将影响我已编写过的另一个python脚本。任何建议将不胜感激。提前感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:0)

很难找到问题的确切位置:)

但是python有类似os.walk的东西,让我举个例子:

import os

root_directory = '/home/xyz/some_root_dir/'

def is_csv(fname):
    return fname.endswith('.csv')

csv_files = []

for directory, subdirectories, files_names in os.walk(root_directory):
    for fname in files_names:
        if is_csv(fname):
            csv_files.append(
                {
                    'directory': directory,
                    'fname': fname
                }
            )

print(csv_files)

这在我的测试用例中:

[
    {'directory': '/home/xyz/some_root_dir', 'fname': 'my.csv'},
    {'directory': '/home/xyz/some_root_dir/test2/test31', 'fname': 'myohter3.csv'}
    {'directory': '/home/xyz/some_root_dir/test2/test31', 'fname': 'myohter.csv'}
]

这肯定会帮助您获取所有csv文件 - 您可以根据需要修改is_csv方法。我无法帮助您汇总数据:)

但是一旦你阅读了所有的数据,这应该不是什么大问题。

好的,现在开始有趣了。我做得非常快 - 可能写得更好,但这是一个很好的起点,我们有上一步的文件列表,让我们做下一步:

import csv
import os
from datetime import datetime

data = {}

# gather the data;
for fdata in csv_files:
    with open(os.path.join(fdata['directory'], fdata['fname']), 'r') as f:
        reader = csv.reader(f, delimiter='|', quotechar='"')
        rows = list(reader)
        data[fdata['fname']] = rows  # we can't store it per datetime here, because can lost data

# ok we have a data now in format:

# {
#     'other3.csv': [
#         ['Datetime', 'Egen1_NotCum_kWh', 'Egen2_NotCum_kWh', 'Egen3_NotCum_kWh'],
#         ['2016-09-04 13:45:00', '643.23', '649', '654'],
#         ['2016-09-04 14:00:00', '612.21', '672', '666'],
#         ['2016-09-04 14:15:00', '721.3', '719', '719'],
#         ['2016-09-04 14:30:00', '730', '721', '725'],
#         ['2016-09-04 14:45:00', '745', '725', '731']],
#     'my.csv': ...
# }

# convert the string data to python Datetime

DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"

for fname, inner_data in data.iteritems():
    for row in inner_data[1:]:  # skip headers
        p_datetime = datetime.strptime(row[0], DATETIME_FORMAT)
        row[0] = p_datetime

# now the aggregates;

def get_all_rows_in_dates(start_date, end_date, data):
    headers = data[data.keys()[0]][0]
    data_rows = []
    for fname, inner_data in data.iteritems():
        for row in inner_data[1:]:  # skip the header
            if start_date <= row[0] < end_date:
                data_rows.append(row)

    return headers, data_rows

def aggregate_col_12(values):
    values  = map(float, values)
    return sum(values)

def aggregate_col_3(values):
    values  = map(float, values)
    return sum(values) / float(len(values))

def count_aggregates(rows_in_dates, start_date):
    col1 = []
    col2 = []
    col3 = []
    for row in rows_in_dates[1:]:  # skip headers
        col1.append(row[1])
        col2.append(row[2])
        col3.append(row[3])
    return [start_date.strftime(DATETIME_FORMAT),
        aggregate_col_12(col1), aggregate_col_12(col2), aggregate_col_3(col3)]


def write_results(headers, aggregate, fname):
    data = []
    data.append(headers)
    data.append(aggregate)
    with open(fname, 'w+') as f:
        writer = csv.writer(f, delimiter='|', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        writer.writerows(data)


start_date = datetime(2016, 9, 4, 13, 0, 0)
end_date = datetime(2016, 9, 4, 14, 0, 0)

headers, to_aggregate = get_all_rows_in_dates(
    start_date,
    end_date,
    data)

aggregates = count_aggregates(to_aggregate, start_date)
write_results(headers, aggregates, 'from_{}_to_{}.csv'.format(
    start_date.strftime(DATETIME_FORMAT),
    end_date.strftime(DATETIME_FORMAT),
))

注意 - 在代码中使用适当的分隔符和quotechar。 这只是开始 - 你可以使用它作为一个开始 - 每日聚合 - 应该可以使用此代码实现,但如果你想要一个小时每秒行csv - 你需要包装一点。

如果您有任何疑问 - 请做。