簡體   English   中英

For跨多個文件夾循環以對多個CSV文件中的日期時間進行重采樣並使用自動生成的文件名進行導出

[英]For Loop across Multiple Folders to Resample Datetime in Multiple CSV Files and Export with File Name Automatically Generated

我的計算機上的文檔中的各個文件夾中都有許多數據框(csv文件)。 所有csv文件具有相同的列數,其中每列的名稱相同且順序相同,但是,文件中存在的數據行數不同。 所有文件的第一列均為“ Datetime”,其中“ YYYYMMDD HH:MM:SS”記錄在數據行的下方。

我想對所有數據框重新采樣,以從原始文件中創建每小時,每天和每月的數據。 csv文件中的某些列要求對小時,天和月進行數據求和,而其他列則需要對這些時間范圍內的數據求平均(在所有csv文件中均保持一致)。 我希望每個原始的csv文件都有自己的每小時,每日和每月版本。

所有csv文件都存在於以下輸入路徑中,但實際上位於該輸入路徑中的其他文件中:

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

例如,在“清潔”文件夾中還有兩個文件夾,而這些文件夾中還有其他文件夾,其中包含所有csv文件。 我想讀取“ Clean”文件夾之后存在的所有csv文件,而不必編寫多個“ inputpaths”並對文件進行重新采樣,如前所述。

然后,我想將這些重新采樣的數據幀導出到它們來自的文件夾,並在它們的名稱中添加“小時”,“天”或“月”。

以下是csv文件的片段示例。

在此處輸入圖片說明

例如,我想將15分鍾間隔數據重新采樣為每小時,每天和每月的數據。 重新采樣時,前兩列需要加總,而第三列需要在重新采樣的時間范圍內取平均值。 我知道df.resample('h')。sum()將對一小時的數據求和,而* .mean()將對一小時的數據求平均值,但是當不同的列需要不同的重采樣然后想要將所有這些列組合在一起,然后將每小時,每天或每月的文件導出到其各自的位置,文件名已自動更改為現在每小時,每天或每月的文件名。

我意識到這是非常有描述性的,但是這導致了我各種各樣的延遲,重新放置csv文件將影響我已經編寫的另一個python腳本。 任何建議將不勝感激。 預先感謝您提供的任何幫助。

很難找到問題所在:)

但是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占用一個小時,則需要將其包裝一些。

如果您有任何疑問-請這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM