【问题标题】:How can I optimise operations on dataframe by avoiding loops in python?如何通过避免 python 中的循环来优化数据帧上的操作?
【发布时间】:2020-04-18 12:29:45
【问题描述】:

如何避免for index, row in df.iterrows()

我的数据是这样的:

import pandas as pd

keys = ['Address', 'CoordinateX', 'CoordinateY']
values = [['Addr1', 'Addr2', 'Addr3'], [0, 1, 1], [9, 2, 1]]
addresses = dict(zip(keys, values))
df = pd.DataFrame(addresses, columns=keys)
R = 1

df 可以显示为:

  Address  CoordinateX  CoordinateY
0   Addr1            0            9
1   Addr2            1            2
2   Addr3            1            1

我的任务是添加一个新列Counts,它存储位于同一区域内的地址数量 - 一定半径的圆R。但是,在最终数据帧上,我只希望每个区域有一个代表地址。所以计算后的输出是:

  Address  CoordinateX  CoordinateY  Counts
0   Addr1            0            9       1
1   Addr2            1            2       2

最初,我有这个代码:

df_X = pd.DataFrame() # to fill with counts
for idx, row in df.iterrows():
  x1, y1 = row['CoordinateX'], row['CoordinateY']
  addr_count = 0
  indices = [] # to collect idx2 for dropping in df_X
  df2 = df.copy()
  for idx2, row2 in df2.iterrows():
    x2, y2 = row2['Longitude'], row2['Lattitude']
    distance = math.sqrt((x2-x1)**2 + (y2-y1)**2)
    if distance <= R:
      addr_count += 1
      indices.append(idx2)
  if addr_count > 0:
    row['Count'] = addr_count
    df_X = df_X.append(row, ignore_index=True)
    df.drop(indices, inplace=True) # to exclude the rows in next iteration
df_X.shape

所以有 2 个循环 - 类似数据的外部和内部。 因为我的原始数据框有几千行,所以我想使用pd.apply() 优化计算。这是我用pd.apply 替换内部循环的代码:

def count_items(x1, y1, r, df):
  def is_outside(x2, y2): return r < math.sqrt((x2-x1)**2 + (y2-y1)**2)
  df_new = df[df.apply(lambda a: is_outside(a['CoordinateX'], a['CoordinateY']), axis=1)] # new set with distant addresses only
  return df_new, len(df.index) - len(df_new.index)

def get_counted(r, df):
  df_X = pd.DataFrame() # to fill with counts
  for idx, row in df.iterrows():
    x1, y1 = row['CoordinateX'], row['CoordinateX']
    df2 = df.copy()
    df3, addr_count = count_items(x1, y1, r, df2) # df3 contains now only distant addresses
    if addr_count > 0:
      row['Count'] = addr_count
      df_X = df_X.append(row, ignore_index=True)
    df = df3.copy()
  return df_X

df_c = df.copy()
df_addrX = get_counted(R, df_c)

而且我不知道如何以同样的方式使用外部循环来增强部分。有人可以提供建议吗? BR,谢谢!

【问题讨论】:

    标签: python pandas lambda apply


    【解决方案1】:

    您需要的是使用组合功能,您可以找到信息here

    正如他们所说,你可以申请:

    组合('ABCD', 2)

    为了获得:

    AB AC AD BC BD CD

    你的函数的第一个参数是你行上的迭代器,第二个是 2(你想要 2 行的组合)。

    您可以对行的索引进行迭代,例如,您可以获得多个行的索引。

    之后,只要你有几行,你就可以映射或迭代结果,以应用计算距离的函数。

    您可以将所有这些存储在具有以下列的 DataFrame 中:

    第一行索引
    SecondRowIndex
    距离

    然后,只需在两列上创建一个groupby()FirstRowIndexDistance,以便在同一区域找到元素,删除不需要的元素并保留所需的索引。

    最后,选择原始DataFrame中那些索引对应的行,以df.loc为例。

    【讨论】:

    • 我检查了,这仍然需要外部循环来提供数据...
    • 确实,混淆矩阵似乎有帮助,让我考虑一下。
    • 我更新了答案,我找到了一些可以解决您问题的方法。
    • 谢谢,我会探索并告诉你。
    • 您可以迭代行的索引,例如,您需要输入一个迭代器来组合函数。我希望这可能会有所帮助。
    猜你喜欢
    • 2019-11-17
    • 1970-01-01
    • 2021-12-07
    • 2015-02-17
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 2015-07-29
    • 2020-06-15
    相关资源
    最近更新 更多