pandas 根据另一个数据框计算总和

llew8vvj  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(67)

第一个 Dataframe (df):
| 开始|端|
| --|--|
| 六点十五分|六点十五分零六秒|
| 六点十五分|六点十五分|
| 六点十五分|六点十五分零一秒|
| 六点十五分零一秒|六点十五分零六秒|
| 六点十五分零一秒|6点15分15秒|
| 六点十五分零一秒|六点十五分零九秒|
| 六点十五分零一秒|六点十五分零九秒|
| 六点十五分零二秒|六点十五分零六秒|
| 六点十五分零二秒|六点十五分零八秒|
| 六点十五分零二秒|六点十五分零九秒|
df2
| 周期(1秒时间增量)|总|
| --|--|
| 六点十五分| 2 |
| 六点十五分零一秒| 5 |
| 六点十五分零二秒| 8 |
如何在df2中计算total而不使用循环?对于df2中的每个周期,需要从df开始的行的总和,前提是start <= periodend >= period (total)。例如df2 = x中的6:15:02

from datetime import datetime, timedelta

x = datetime(year=2023,month=10, day=6, hour=6, minute=15, second=2).time()

df = pd.DataFrame({'start': ['6:15:00', '6:15:00', '6:15:00', '6:15:01', '6:15:01', '6:15:01', '6:15:01', '6:15:02', '6:15:02', '6:15:02'],
              'end': ['6:15:06', '6:15:00', '6:15:01', '6:15:06', '6:15:15', '6:15:09', '6:15:09', '6:15:06', '6:15:08', '6:15:09']})

df['start'] = pd.to_datetime(df['start'], yearfirst=True).dt.time
df['end'] = pd.to_datetime(df['end'], yearfirst=True).dt.time

start = datetime(year=2023,month=10, day=6, hour=6, minute=15, second=0)
end = datetime(year=2023,month=10, day=6, hour=6, minute=15, second=2)
df2 = pd.DataFrame({"periods (1 sec timedelta)": pd.date_range(start=start, end=end, freq=timedelta(seconds=1)), "total": None})
df2["periods (1 sec timedelta)"] = pd.to_datetime(df2["periods (1 sec timedelta)"], yearfirst=True).dt.time

total = len(df[(df['start'] <= x) & (df['end'] >= x)])

total = 8。如果计算df2中的每一行,则需要花费大量时间。有没有更有效的方法?

k97glaaz

k97glaaz1#

将时间类列解析为timedelta数组,然后调用一个函数,该函数将返回满足给定条件的行数。这里的技巧是用numba编译函数,以达到C语言的速度,因为你的数组是大numba,这将是提高效率和内存管理的理想方法

from numba import njit

@njit
def func(period, start, end):
    for p in period:
        mask = (start <= p) & (end >= p)
        yield sum(mask)

def to_timedelta_arr(col):
    return pd.to_timedelta(col.astype(str)).to_numpy()

df2['total'] = list(func(to_timedelta_arr(df2['periods (1 sec timedelta)']),
                         to_timedelta_arr(df['start']), to_timedelta_arr(df['end'])))
periods (1 sec timedelta)  total
0                  06:15:00      3
1                  06:15:01      6
2                  06:15:02      8
vcudknz3

vcudknz32#

可能是这样的东西应该做的工作:

def calculate_total(period):
    return len(df1[(df1['start'] <= period) & (df1['end'] >= period)])

df2['total'] = df2['periods (1 sec timedelta)'].apply(calculate_total)

calculate_total函数将计算df1中的行

  • 其中start time小于或等于input periodend time大于或等于输入周期。

然后,将此函数应用于df2['periods (1 sec timedelta)']的每一行,以计算并分配df2中的'total' column

相关问题