python - 如何有效地将行附加到 pandas DataFrame

标签 python performance pandas

我正在尝试创建一个虚拟文件以便之后进行一些 ML 预测。输入大约有 2000 条“路线”,我想创建一个虚拟对象,其中包含 7 天的年-月-日-小时组合,这意味着每条路线 168 行,总共约 35 万行。 我面临的问题是 Pandas 在追加特定大小的行时变得非常慢。

我正在使用以下代码:

DAYS = [0, 1, 2, 3, 4, 5, 6]
HODS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]

ISODOW = {
    1: "monday",
    2: "tuesday",
    3: "wednesday",
    4: "thursday",
    5: "friday",
    6: "saturday",
    7: "sunday"
}

def createMyPredictionDummy(start=datetime.datetime.now(), sourceFile=(utils.mountBasePath + 'routeProperties.csv'), destFile=(utils.outputBasePath + 'ToBePredictedTTimes.csv')):
    '''Generate a dummy file that can be used for predictions'''
    data = ['route', 'someProperties']
    dataFile = data + ['yr', 'month', 'day', 'dow', 'hod']

    # New DataFrame with all required columns
    file = pd.DataFrame(columns=dataFile)

    # Old data frame that has only the target columns    
    df = pd.read_csv(sourceFile, converters=convert, delimiter=',')
    df = df[data]

    # Counter - To avoid constant lookup for length of the DF
    ix = 0

    routes = df['route'].drop_duplicates().tolist()
    # Iterate through all routes and create a row for every route-yr-month-day-hour combination for 7 day -->  about 350k rows
    for no, route in enumerate(routes):
        print('Current route is %s which is no. %g out of %g' % (str(route), no+1, len(routes)))
        routeDF = df.loc[df['route'] == route].iloc[0].tolist()
        for i in range(0, 7):
            tmpDate = start + datetime.timedelta(days=i)
            day = tmpDate.day
            month = tmpDate.month
            year = tmpDate.year
            dow = ISODOW[tmpDate.isoweekday()]
            for hod in HODS:
                file.loc[ix] = routeDF + [year, month, day, dow, hod] # This is becoming terribly slow
                ix += 1
    file.to_csv(destFile, index=False)
    print('Wrote file')

我认为主要问题在于用 .loc[] 追加行 - 有什么方法可以更有效地追加行吗? 如果您有任何其他建议,我很乐意听到所有建议!

谢谢,最好的,

卡比

最佳答案

(这是一个很长的评论,而不是一个答案,对不起,但是没有示例数据我不能运行太多...)

因为在我看来你是按顺序一次添加一行(即数据帧由按顺序访问的整数索引)并且你总是知道列的顺序,你可能最好创建一个列表列表,然后将其转换为 DataFrame,即定义类似于 file_list = [] 的内容然后替换行 file.loc[ix] = ...通过:

file_list.append(routeDF + [year, month, day, dow, hod])

最后,你可以定义

file = pd.DataFrame(file_list, columns=dataFile)

如果您的所有数据都是固定类型(例如 int,取决于您的 routeDF 是什么,并且在创建数据帧之前不转换 dow),您可能会更好地预分配一个 numpy 数组并写入它,但我很确定向列表中添加元素不会成为代码的瓶颈,因此这可能是过度优化。

另一种减少代码更改的方法是通过创建一个充满 NaN 的 DataFrame 而不是没有行的 DataFrame 来预先分配足够的空间,即将文件的定义更改为(在将带有 drop_duplicates 的行向上移动之后):

file = pd.DataFrame(columns=dataFile, index=range(len(routes)*168))

我很确定这比你的代码快,但它可能仍然比上面的列表列表方法慢,因为在你填写数据之前它不知道期望的数据类型(它可能例如转换你的 float 的整数是不理想的)。但是同样,一旦你摆脱了由于在每一步扩展 DataFrame 而导致的连续重新分配,这可能不再是你的瓶颈(双循环可能是。)

关于python - 如何有效地将行附加到 pandas DataFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50964480/

相关文章:

Javascript - 连接字符串/变量时使用 + 和 之间的区别?

python - 在每个客户的客户表单 View 中显示逾期付款总和

python - Python 3 和 Windows 64 中的内存错误

android - 在我的特殊情况下,logcat 不显示来自库项目的日志

python - 如何将新列添加到现有数据框并用另一列中的部分数据填充它?

python - Pandas:根据另一列中的键将字典值映射到现有列以替换 NaN

python - 强制所有行在条件后取值

python - 如何使用关键字作为变量名?

python - 使用 Python 代码清除控制台时如何修复 "TERM environment variable not set"?

python - 为什么这个 C++ 代码只比 Python 快一点点?