如何过滤pandas数据框?

时间:2017-04-16 20:36:00

标签: python pandas dataframe

我正在处理以下数据框:

      id1     id2      lat        lon
   0  1       2        18.46290   -66.10301
   1  1       2        37.549     -71.477
   2  1       2        41.490     -71.326
   3  0       0        0.0        0.0
   4  1       3        42.058     -70.577
   5  1       3        42.402     -70.642
   6  1       3        41.589     -71.281
   7  1       3        37.649     -71.440
   8  0       0        0.0        0.0
   9  2       2        18.462     -66.103
  10  2       2        18.44857   -66.089
  11  2       2        42.242     -70.97
  12  0       0        0.0        0.0 

以上数据是轨迹数据,我想找到所有在一个城市开始或结束的轨迹,比如NYC。

每个轨迹都有多个点,轨迹由上面df中的所有0行分隔。

因此,0-2行是一个轨迹,4-7行是另一个轨道,依此类推。 (即使需要删除所有0行,“id1”和“id2”一起标识不同的轨迹,就像我们在id1或id2发生变化时所看到的那样,我们正在获得新的轨迹)。

我有另一个df,比如df2,其中包含我想要限制轨迹的城市特定区域的所有坐标:

          lat     lon
       0  40.711  -70.000
       1  40.734  -70.099
       2  40.740  -70.110
       3  40.750  -70.120

我希望将df1中每条轨迹的第一个点和最后一个点与df2中的坐标相匹配,如果第一个点或最后一个点与df2中的任何坐标对匹配,我我只想保留这些轨迹。

(正如我所提到的,我想只保留在城市中结束和开始的轨迹,所以在df1中的“行0-2”的情况下,我想要匹配第0行的lat和lon(起始点)和df2的第2行(轨迹的终点),对于“4-7行”,我会匹配第4行的lat和lon(起始点)然后匹配第7行(结束点),依此类推整个df)

如果我只需要搜索特定“lat”和“lon”的行,也许我可以找到解决方案,如下面的代码所示:

       mask = ((df["lat"].isin(df2["lat"])) && (df["lon"].isin(df2["lon"])))
       new_df = pd.DataFrame(df[mask])
       new_df.head()

但我必须查询每个轨迹的起点和终点,它们以0分隔。我不知道如何做到这一点。

我希望问题很清楚,如果有什么不清楚,请告诉我。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:2)

考虑以下输入DataFrame:

In [158]: df
Out[158]:
    id1  id2       lat       lon
0     1    2  18.46290 -66.10301
1     1    2  37.54900 -71.47700
2     1    2  41.49000 -71.32600
3     0    0   0.00000   0.00000
4     1    3  42.05800 -70.57700   # matching point
5     1    3  42.40200 -70.64200
6     1    3  41.58900 -71.28100
7     1    3  37.64900 -71.44000
8     0    0   0.00000   0.00000
9     2    2  18.46200 -66.10300
10    2    2  18.44857 -66.08900
11    2    2  42.24200 -70.97000   # matching point
12    0    0   0.00000   0.00000

In [159]: df2
Out[159]:
      lat     lon
0  40.711 -70.000
1  40.734 -70.099
2  40.740 -70.110
3  40.750 -70.120
4  42.058 -70.577   # matching point
5  42.242 -70.970   # matching point

让我们找到所有轨迹的起点和终点的索引:

In [164]: idx = df.loc[(df.id1!=0) & (df.id2!=0)] \
     ...:         .groupby(['id1','id2'])['lat','lon'] \
     ...:         .apply(lambda x: pd.Series([x.index[0], x.index[-1]])) \
     ...:         .stack() \
     ...:         .values
     ...:

In [165]: idx
Out[165]: array([ 0,  2,  4,  7,  9, 11], dtype=int64)

让我们将坐标乘以100并将它们截断为整数(因为比较Python / Pandas中的浮点数是“邪恶的”):

df2 = df2.mul(100).astype(int)

# `d` - will contain only starting and ending points for each trajectory
d =  df.loc[idx]
d.loc[:, ['lat','lon']] = d[['lat','lon']].mul(100).astype(int)

现在我们将所有坐标都整数:

In [181]: d
Out[181]:
    id1  id2   lat   lon
0     1    2  1846 -6610
2     1    2  4149 -7132
4     1    3  4205 -7057
7     1    3  3764 -7144
9     2    2  1846 -6610
11    2    2  4224 -7097


In [163]: df2
Out[163]:
    lat   lon
0  4071 -7000
1  4073 -7009
2  4074 -7011
3  4075 -7012
4  4205 -7057
5  4224 -7097

所以我们可以轻松合并它们:

In [185]: d.merge(df2)
Out[185]:
   id1  id2   lat   lon
0    1    3  4205 -7057
1    2    2  4224 -7097

并将其与原始DF合并:

In [186]: d.merge(df2)[['id1','id2']].merge(df)
Out[186]:
   id1  id2       lat     lon
0    1    3  42.05800 -70.577
1    1    3  42.40200 -70.642
2    1    3  41.58900 -71.281
3    1    3  37.64900 -71.440
4    2    2  18.46200 -66.103
5    2    2  18.44857 -66.089
6    2    2  42.24200 -70.970