提高熊猫行拆分的效率

时间:2019-06-25 10:01:03

标签: python pandas

我有一个数据帧(df),其中包含如下数据(仅提供一行):

df_raw_data = pd.DataFrame(data = {'checkin':datetime.date(2019, 01, 01), 'checkout':datetime.date(2019, 01, 05), 'booking_id':1234, 'tag':'A', 'rooms':2}, index = [0])

我想编写一个代码块,该代码块读取df_raw_data的每一行并创建一个新的df_split_data,该数据将df_raw_data的每一行如下:

df_split_data = pd.DataFrame(data = {'date':[datetime.date(2019, 01, 01), datetime.date(2019, 01, 02), datetime.date(2019, 01, 03), datetime.date(2019, 01, 04)], 'checkin':[datetime.date(2019, 01, 01), datetime.date(2019, 01, 01), datetime.date(2019, 01, 01), datetime.date(2019, 01, 01)], 'checkout':[datetime.date(2019, 01, 05), datetime.date(2019, 01, 05), datetime.date(2019, 01, 05), datetime.date(2019, 01, 05)], 'booking_id':[1234, 1234, 1234, 1234], 'tag':['A', 'A', 'A', 'A'], 'rooms':[2, 2, 2, 2]})

基本上,每次预订都应划分为天数=(结帐-签到),并以新列的形式获取日期,而其他列则保持完全相同。

我尝试使用如下所示的for循环进行此操作

df_split_data = pd.DataFrame()
for i in range(len(df_raw_data)):
    df_1 = df_raw_data[i:i+1]
    df_1.reset_index(inplace = True)
    checkin_date = df_1['checkin'][0]
    checkout_date = df_1['checkout'][0]
    rooms = df_1['rooms'][0]
    booking_id = df_1['booking_id'][0]
    tag = df_1['tag'][0]
    los = df_1['los'][0]
    #los is a column which checkout - checkin in days
    datelist = pd.date_range(checkin_date, periods=los).tolist()
    datelist = [x.date() for x in datelist]
    df_2 = pd.DataFrame(data = {'date':datelist})
    df_2['checkin'] = checkin_date
    df_2['checkout'] = checkout_date
    df_2['rooms'] = rooms
    df_2['booking_id'] = booking_id
    df_2['tag'] = tag
    df_split_data =  df_split_data.append(df_2)

这样做可以得到正确的结果,但是当有200万个以上的条目时,执行将花费很长时间。

是否有更有效的方法?

1 个答案:

答案 0 :(得分:1)

这是将index.repeatDataFrame.locpandas.to_timedelta一起创建扩展的DataFrame,然后使用groupby.cumcount和{{3}}来更新date列中的值的一种方法:

df_split_data = df_raw_data.loc[
    df_raw_data.index.repeat(
        (df_raw_data['checkout'] - df_raw_data['checkin']).dt.days + 1)]

df_split_data['date'] = (pd.to_datetime(df_split_data['date']) + 
                         pd.to_timedelta(df_split_data.groupby(df_split_data.columns.tolist()).cumcount(), unit='d'))

[出]

      checkin    checkout  booking_id tag  rooms       date
0  2019-01-01  2019-01-05        1234   A      2 2019-01-01
0  2019-01-01  2019-01-05        1234   A      2 2019-01-02
0  2019-01-01  2019-01-05        1234   A      2 2019-01-03
0  2019-01-01  2019-01-05        1234   A      2 2019-01-04
0  2019-01-01  2019-01-05        1234   A      2 2019-01-05