【问题标题】:How to loop through columns of a pandas DataFrame [duplicate]如何循环遍历熊猫数据框的列[重复]
【发布时间】:2019-01-15 22:10:44
【问题描述】:

我有一个包含数千行的 CSV 文件。该文件有 3 列日期、时间和值。我想首先遍历日期列,然后是时间列,然后在两个特定时间之间添加值。 Pandas 中是否有任何功能可以实现这一点?下面是我的示例 CSV。日期不是连续的,而是按升序排列的。

Date    Time    Value
29-Jan-18   11:00   10
29-Jan-18   12:00   11
29-Jan-18   13:00   12
29-Jan-18   14:00   13
31-Jan-18   11:00   90
31-Jan-18   12:00   91
31-Jan-18   13:00   92
31-Jan-18   14:00   93

我正在寻找输出为“对于 2018 年 1 月 29 日和时间 11 到 13,值的总和是 33。”

不完全是 11-12,但有一个系列。将对 9-10,10-11,11-13,13-15 进行计算,但在 CSV 文件中,每个小时都存在。

【问题讨论】:

  • 时间,你是11:12,然后是12:13,然后是13:14还是??
  • 不完全是 11-12,但有一个系列。计算将针对 9-10,10-11,11-13,13-15 进行,但在 csv 文件中每小时存在一次。
  • 嗯,你的滚动窗口是多少? 2 或 3,因为您有 9:10,10:11,其滚动窗口为 2,但您也有 11:13,而滚动窗口为 3.. 为什么要更改?为什么不 11:12
  • 你能包含你期望的输出吗?
  • @Onyambu 这就是我面临的挑战。每天唯一固定的时间范围是 9-10,10-11,11-13,13-15

标签: python pandas dataframe datetime for-loop


【解决方案1】:

您可以通过使用resample 方法来实现这一点。

首先,您需要合并日期列和时间列以创建单个日期时间索引。假设您的两列是字符串(如果不是,您可以在它们上调用as_type(str)),您可以连接这些列,将它们转换为datetime 列,然后将datetime 列转换为DatetimeIndex数据帧。

然后调用 resample 并将规则设置为 '3H' 以创建宽度为 3 小时的垃圾箱并将 base=11 设置为从上午 11 点开始(当然,您可以根据需要/需要更改此设置)和 sum在 DataFrame 上。

这是一个例子:

import pandas as pd
import datetime as dt

df.index = pd.DatetimeIndex(pd.to_datetime(df.Date.str.cat(df.Time, sep=' ')))
df = df.resample('1H').sum() # to fill missing values
# get values for 9 & 10
df1 = df[(dt.time(9) <= df.index.time) & (df.index.time <= dt.time(10))]
# get values for 11-13 & 13-15
two_hour_ranges = df[df.index.time >= dt.time(11)].resample('2H', base=11).sum()
df2 = two_hour_ranges[(dt.time(11) <= two_hour_ranges.index.time) & (two_hour_ranges.index.time < dt.time(15))]

# merge
df = pd.concat([df1, df2]).sort_index()

使用您给定的数据作为输入,df 的示例输出(我添加了 1/29 和 1/31 的 9:00 和 10:00 的值):

                     Value
Date                     
2018-01-29 09:00:00      4
2018-01-29 10:00:00      5
2018-01-29 11:00:00     21
2018-01-29 13:00:00     25
2018-01-30 09:00:00      0
2018-01-30 10:00:00      0
2018-01-30 11:00:00      0
2018-01-30 13:00:00      0
2018-01-31 09:00:00     70
2018-01-31 10:00:00     80
2018-01-31 11:00:00    181
2018-01-31 13:00:00    185

这里是resample 上的文档以获取更多信息:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.resample.html

【讨论】:

  • 如果时间是每次 3 小时,但小时范围是 9-10,10-11,11-13,13-15 并且每天都是固定的,这将起作用。跨度>
【解决方案2】:

主要思想是将您的日期/时间列转换为datetime 对象,然后使用这些对象进行日期过滤。我以为它们是字符串开始的。

我不确定您的日期是如何传入的,但希望您能弄清楚如何从中创建datetime 对象。如果没有,请告诉我,我们可以更新。下面是一个示例,说明如何按日期过滤并将开始/结束日期的值相加:

import numpy as np
import pandas as pd
import datetime

cols = ["Date", "Time", "Value"]

rows = [["29-Jan-18", "11:00", 10],
        ["29-Jan-18", "12:00", 11],
        ["29-Jan-18", "13:00", 12],
        ["29-Jan-18", "14:00", 13],
        ["31-Jan-18", "11:00", 90],
        ["31-Jan-18", "12:00", 91],
        ["31-Jan-18", "13:00", 92],
        ["31-Jan-18", "14:00", 93]]

df = pd.DataFrame(rows, columns=cols)

df['datetime_str'] = df['Date'].str.cat(df['Time'].astype(str), sep=" ")
df['datetime'] = df['datetime_str'].apply(lambda d: datetime.datetime.strptime(d, '%d-%b-%y %H:%M'))
print(df)
print()

# Hopefully you can figure out how to beat incoming start/end date into datetime.
# If not, let me know how the start/end are coming in and we can write a function to do it
start_date = datetime.datetime.strptime("29-Jan-18 11:00", '%d-%b-%y %H:%M')
end_date = datetime.datetime.strptime("29-Jan-18 13:00", '%d-%b-%y %H:%M')

value_sum = df[ (df['datetime'] >= start_date) & (df['datetime'] <= end_date) ]['Value'].sum()
print("Value sum from " + str(start_date) + " to " + str(end_date) + ": ", value_sum)

# Works accross days as well                                                                                                                                                                                
start_date = datetime.datetime.strptime("29-Jan-18 13:00", '%d-%b-%y %H:%M')
end_date = datetime.datetime.strptime("31-Jan-18 13:00", '%d-%b-%y %H:%M')

value_sum = df[ (df['datetime'] >= start_date) & (df['datetime'] <= end_date) ]['Value'].sum()
print("Value sum from " + str(start_date) + " to " + str(end_date) + ": ", value_sum)

这个输出:

        Date   Time  Value     datetime_str            datetime
0  29-Jan-18  11:00     10  29-Jan-18 11:00 2018-01-29 11:00:00
1  29-Jan-18  12:00     11  29-Jan-18 12:00 2018-01-29 12:00:00
2  29-Jan-18  13:00     12  29-Jan-18 13:00 2018-01-29 13:00:00
3  29-Jan-18  14:00     13  29-Jan-18 14:00 2018-01-29 14:00:00
4  31-Jan-18  11:00     90  31-Jan-18 11:00 2018-01-31 11:00:00
5  31-Jan-18  12:00     91  31-Jan-18 12:00 2018-01-31 12:00:00
6  31-Jan-18  13:00     92  31-Jan-18 13:00 2018-01-31 13:00:00
7  31-Jan-18  14:00     93  31-Jan-18 14:00 2018-01-31 14:00:00

Value sum from 2018-01-29 11:00:00 to 2018-01-29 13:00:00:  33
Value sum from 2018-01-29 13:00:00 to 2018-01-31 13:00:00:  298

【讨论】:

  • 这看起来不错,但具有挑战性的部分是循环遍历日期。它们按升序排列,但不是连续的。比如 1 月 1 日、1 月 2 日、1 月 3 日、1 月 6 日、1 月 8 日、1 月 9 日、1 月 10 日等
  • 我不确定我是否遵循:这里的日期也不连续。无论日期的连续性如何,上面的代码都将工作多天。我添加了一个示例。
猜你喜欢
  • 2017-06-08
  • 2020-11-20
  • 1970-01-01
  • 2017-01-15
  • 1970-01-01
  • 2021-12-18
  • 2021-08-25
相关资源
最近更新 更多