当前位置: 首页 > 知识库问答 >
问题:

如何加快熊猫数据帧迭代涉及2个不同的数据帧复杂的条件?

谭卜鹰
2023-03-14

我有一个大约300000行的熊猫数据帧a。每行都有一个纬度和经度值。

我还有一个大约10000行的第二个数据帧B,它有一个ID号,一个最大和最小纬度,以及一个最大和最小经度。

对于A中的每一行,我需要B中对应行的ID,以便A中行的纬度和经度包含在B中行表示的边界框中。

到目前为止,我有以下几点:

ID_list = []

for index, row in A.iterrows():
    filtered_B = B.apply(lambda x : x['ID'] if row['latitude'] >= x['min_latitude']
                                            and row['latitude'] < x['max_latitude'] \
                                            and row['longitude'] >= x['min_longitude'] \
                                            and row['longitude'] < x['max_longitude'] \
                                            else None, axis = 1)
    ID_list.append(B.loc[filtered_B == True]['ID']

创建ID_列表变量的目的是将其作为ID列添加到A中。包含大于或等于以及小于条件,以便A中的每一行只有一个来自B的ID。

上面的代码在技术上是可行的,但它每分钟完成大约1000行,这对于如此大的数据集是不可行的。

任何提示将不胜感激,谢谢。

编辑:示例数据帧:

A:

B:

预期产出:

ID_list = [9ae8704, 0uh0478, 3ef4522, 0uh0478]

共有3个答案

田志尚
2023-03-14

一个很好的选择可能是执行跨产品合并并删除不需要的列。例如,您可能会这样做:

AB_cross = A.merge(
    B
    how = "cross"
)

现在我们有了一个巨大的数据框,里面有所有可能的匹配,其中B中的ID(或者可能没有,我们还不知道)可能有符合A中的点的边界。这很快,但在内存中形成了一个大数据集,因为我们现在有一个数据集是30000x10000行长。

现在,我们需要通过相应地过滤数据集来应用我们的逻辑。这是一个numpy过程(据我所知),所以它是矢量化的,速度非常快!我还要说,在之间使用可能会更容易,从而使代码更具语义。

请注意,下面我使用了。between(inclusive='left')表示希望查看long/lat是否为minu long的事实

ID_list = AB_cross['ID'].loc[
    AB_cross['longitude'].between(AB_cross['min_longitude'], AB_cross['max_longitude'], inclusive = 'left') &
    AB_cross['latitude'].between(AB_cross['min_latitude'], AB_cross['max_latitude'], inclusive = 'left')
]

华衡
2023-03-14

我们可以在b上创建一个多间隔索引,然后使用常规的loc索引将其与来自a行的元组结合起来。区间索引在这种情况下很有用,当我们有一个由低值和高值组成的表来将变量存储到其中时。

from io import StringIO

import pandas as pd

a = pd.read_table(StringIO("""
    location    latitude    longitude
    1   -33.81263   151.23691
    2   -33.994823  151.161274
    3   -33.320154  151.662009
    4   -33.99019   151.1567332
"""), sep='\s+')

b = pd.read_table(StringIO("""
    ID  min_latitude    max_latitude    min_longitude   max_longitude
    9ae8704     -33.815     -33.810     151.234     151.237
    2ju1423     -33.555     -33.543     151.948     151.957
    3ef4522     -33.321     -33.320     151.655     151.668
    0uh0478     -33.996     -33.990     151.152     151.182
"""), sep='\s+')

lat_index = pd.IntervalIndex.from_arrays(b['min_latitude'], b['max_latitude'], closed='left')
lon_index = pd.IntervalIndex.from_arrays(b['min_longitude'], b['max_longitude'], closed='left')
index = pd.MultiIndex.from_tuples(list(zip(lat_index, lon_index)), names=['lat_range', 'lon_range'])
b = b.set_index(index)

print(b.loc[list(zip(a.latitude, a.longitude)), 'ID'].tolist())

上面的代码甚至可以处理a行,这些行在b中没有对应的行,方法是用nan优雅地填充这些值。

韦繁
2023-03-14
import geopandas as gpd
from shapely.geometry import box

a_gdf = gpd.GeoDataFrame(a[['location']], geometry=gpd.points_from_xy(a.longitude,
                                                                      a.latitude))
b_gdf = gpd.GeoDataFrame(
    b[['ID']], 
    geometry=[box(*bounds) for _, bounds in b.loc[:, ['min_longitude',
                                                      'min_latitude', 
                                                      'max_longitude', 
                                                      'max_latitude']].iterrows()])

gpd.sjoin(a_gdf, b_gdf)

输出:

 类似资料:
  • 我正在尝试连接到数据帧。它们看起来像这样 期望的最终目标是: 我一直试图使用pd.merge和。连接函数与on='外'设置不成功

  • 假设熊猫数据帧如下所示: 如何将第三行(如row3)提取为pd数据帧?换句话说,row3.shape应该是(1,5),row3.head()应该是:

  • 问题内容: 我有一个大的数据框(几百万行)。 我希望能够对它进行分组操作,而只是按行的任意连续(最好大小相等)的子集进行分组,而不是使用各个行的任何特定属性来确定它们要进入的组。 用例:我想通过IPython中的并行映射将函数应用于每一行。哪行进入哪个后端引擎都没有关系,因为该函数一次基于一行来计算结果。(至少在概念上;实际上是矢量化的。) 我想出了这样的东西: 但这似乎很漫长,并且不能保证大小相

  • 我有两个Pandas Dataframe和,其中是的一部分,我想创建一个Dataframe,其中包含中的code>。 以下是一个例子: 注: 我的DataFrame可能有多个列,但是必须仅在列上进行匹配。

  • 在编程方面,我是一个新手,特别是熊猫。我也很抱歉,我问了一个已经在SF上提到的问题:我并不真正理解这个问题的现有答案。可能重复,但这个答案对新手来说很容易理解,如果不太全面的话。

  • 我有这个熊猫数据框 这就给了我: 我该怎么办 做一个新的人物, 将标题添加到图"标题这里" 以某种方式创建一个映射,这样标签不是29,30等,而是“29周”,“30周”等。 将图表的较大版本保存到我的计算机(例如10 x 10英寸) 这件事我已经琢磨了一个小时了!