【问题标题】:NaN at First Position of Two Columns, By Each Unique ValueNaN 在两列的第一个位置,按每个唯一值
【发布时间】:2019-12-17 14:45:49
【问题描述】:

我正在尝试将数据框中每个唯一 ID 的第一个观察值更改为 NaN。我正在使用已按唯一 ID 和时间戳排序的时间戳和坐标点的数据框。

示例:

    ID        timestamp   latitude  longitude
0    1   6/9/2017 11:20  38.795333  77.008883
1    1   6/9/2017 13:10  38.889011  77.050061
2    1   6/9/2017 16:23  40.748249  73.984191
3    2  6/11/2017 08:35  38.920602  77.222329
4    2  6/11/2017 10:00  42.366211  71.020943
5    2  6/11/2017 20:00  38.897416  77.036833
6    2  6/12/2017 07:30   38.851426  77.042298
7    2  6/12/2017 10:20  38.917346  77.222553
8    3  6/11/2017 09:01  40.782869  73.967544
9    3  6/11/2017 10:03  38.954268  77.449695
10   3  6/11/2017 11:48  38.872875  77.007763
11   3  6/12/2017 11:52  40.776931  73.876155

尝试:

df['latitude'] =\
 df.groupby('ID')['latitude'].apply(lambda x: x[0].np.nan)
df['longitude'] =\
 df.groupby('ID')['longitude'].apply(lambda x: x[0].np.nan)

我怀疑虽然 df 已经分组,但我仍然需要使用 groupby 来按每个唯一 ID 进行操作。我很难考虑如何访问每个第一个值,然后将它们替换为 NaN。

这给出了错误: KeyError: 0

这是所需的输出:

        ID        timestamp   latitude  longitude
    0    1   6/9/2017 11:20        NaN       NaN
    1    1   6/9/2017 13:10  38.889011  77.050061
    2    1   6/9/2017 16:23  40.748249  73.984191
    3    2  6/11/2017 08:35        NaN       NaN
    4    2  6/11/2017 10:00  42.366211  71.020943
    5    2  6/11/2017 20:00  38.897416  77.036833
    6    2  6/12/2017 07:30   38.851426  77.042298
    7    2  6/12/2017 10:20  38.917346  77.222553
    8    3  6/11/2017 09:01        NaN       NaN
    9    3  6/11/2017 10:03  38.954268  77.449695
    10   3  6/11/2017 11:48  38.872875  77.007763
    11   3  6/12/2017 11:52  40.776931  73.876155

编辑(为什么要这样做?):

我正在尝试改编这个版本 this answer to calculate distance and velocity。一切都很好,除了每个值的每个纬度/经度的第一个值是错误的,因为函数在行上计算,不分青红皂白的 ID。查看不同的解决方案,我怀疑我需要类似于 this... 使用 concatshift 计算速度和距离。不过,这对我来说有点难以概念化-因此认为仅替换这些值会比编辑和重新运行更简单-这就是我提出这个问题的原因。

【问题讨论】:

  • 你为什么要这样做?
  • 您介意提供代码来构建您的数据框吗?
  • @Moormanly 如果将变量 s 作为顶部文本的副本,则可以通过调用 pd.read_csv(io.StringIO(s), sep=' +', engine='python') 解析整个数据帧(nb sep 是两个空格,然后一个加号)。
  • 同意上面的cmets。可以通过使用蒙版然后使用where 生成NaN 来实现这一点,但我不知道这背后的动机是什么。
  • 我进行了编辑以提供更多上下文。感谢大家的帮助。

标签: python pandas numpy dataframe pandas-groupby


【解决方案1】:

编辑

从 Moormanly 偷一点,可以把它变成一个单线:

df.loc[df.groupby('ID').head(1).index,
       ['longitude', 'latitude']] = float('nan')

这应该可以解决问题:

indices = df.groupby('ID').head(1).index
df.loc[indices, 'latitude'] = float('nan')
df.loc[indices, 'longitude'] = float('nan')

结果:

       ID        timestamp   latitude  longitude
index                                           
0       1   6/9/2017 11:20        NaN        NaN
1       1   6/9/2017 13:10  38.889011  77.050061
2       1   6/9/2017 16:23  40.748249  73.984191
3       2  6/11/2017 08:35        NaN        NaN
4       2  6/11/2017 10:00  42.366211  71.020943
5       2  6/11/2017 20:00  38.897416  77.036833
6       2  6/12/2017 07:30  38.851426  77.042298
7       2  6/12/2017 10:20  38.917346  77.222553
8       3  6/11/2017 09:01        NaN        NaN
9       3  6/11/2017 10:03  38.954268  77.449695
10      3  6/11/2017 11:48  38.872875  77.007763
11      3  6/12/2017 11:52  40.776931  73.876155

【讨论】:

  • DataFrame.groupby.head 依赖于被排序的时间戳
【解决方案2】:

由于您的 df 已经按 ID 列排序,您可以使用以下技巧将每个唯一 ID 的第一次出现作为布尔掩码:

mask = df.ID != df.ID.shift()

然后将对应的数据设置为NaN

df.loc[mask, ['latitude', 'longitude']] = np.nan

【讨论】:

  • 这在很大程度上取决于行的顺序。哦,哎呀,你的编辑打败了我。
  • 我会详细说明这一点。 OP 提到他们的 ID 是排序的,所以至少对他们来说应该没问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 2011-06-07
  • 1970-01-01
相关资源
最近更新 更多