Судя по всему здесь вы создаете однострочный датафрейм, однако можно создать обычную серию (pd.Series)
datareport = pd.DataFrame({'ODATE': {0:0},
'TENOR': {0:0},
'VDATE': {0:0},
'R': {0:0},
'RC': {0:0},
'DE': {0:0},
'I': {0:0},
'DEB': {0:0},
'D': {0:0}}
Далее вы этот однострочный датафрейм через pd.concat присоединяете к еще одному однострочному датафрейму:
datareport = pd.concat([datareport, pd.DataFrame({'ODATE': {0:row.odate},
'TENOR': {0:tenor(row.ltt)},
'VDATE': {0:row.vdate},
'R': {0:bucket_class_old},
'RC': {0:buckclass(row.odues)},
'DE': {0:row.ball},
'I': {0:0},
'DEB': {0:ball_old},
'D': {0:0}})])
а после этого еще раз к одному однострочному датафрейму
datareport = pd.concat([datareport, pd.DataFrame({'ODATE': {0:row.odate},
'TENOR': {0:tenor(row.ltt)},
'VDATE': {0:row.vdate},
'R': {0:bucket_class_old},
'RC': {0:100},
'DE': {0:difference},
'I': {0:0},
'DEB': {0:ball_old},
'D': {0:0}})])
Вместо них тоже можно использовать pd.Series.
Данный код отрабатывает в среднем за 2.5 миллисикунды
ser1 = pd.Series({'ODATE': 0,
'TENOR': 0,
'VDATE':0,
'R': 0,
'RC': 0,
'DE': 0,
'I': 0,
'DEB': 0,
'D': 0})
ser2 = pd.Series({'ODATE': 0,
'TENOR': 1,
'VDATE':2,
'R': 3,
'RC': 4,
'DE': 5,
'I': 6,
'DEB': 7,
'D': 8})
df = pd.concat([ser1, ser2], axis=1).T
В то время как данный код отрабатывает в среднем за 5.2 миллисекунды, при этом результат аналогичен.
datareport1 = pd.DataFrame({'ODATE': {0:0},
'TENOR': {0:0},
'VDATE': {0:0},
'R': {0:0},
'RC': {0:0},
'DE': {0:0},
'I': {0:0},
'DEB': {0:0},
'D': {0:0}})
datareport2 = pd.DataFrame({'ODATE': {0:1},
'TENOR': {0:2},
'VDATE': {0:3},
'R': {0:4},
'RC': {0:5},
'DE': {0:6},
'I': {0:7},
'DEB': {0:8},
'D': {0:9}})
df2 = pd.concat([datareport1, datareport2])
Так что можете попробовать выиграть в скорости, перебравшись с однострочных датафреймов на серии.