根据另一列的掩码修改 Pandas 数据帧列的符号?



我正在使用从NASA的火球数据API导入的纬度/纬度数据(https://cneos.jpl.nasa.gov/fireballs/(

  • lat/lon数据只有正值
  • 它们的方向(N/S和E/W(位于称为lat-dir/lon-dir的不同列中
  • 数据帧如下所示。
  • 现在我想:
  • 如果"纬度"=="S",则将任何lat值转换为负值(乘以 -1(
  • 如果"lon-dir" == 'W',则将lon值转换为负值

以下是我创建数据框的大致方式:

import requests 
import pandas as pd
response = requests.get('https://ssd-api.jpl.nasa.gov/fireball.api')
j = response.json()
df = pd.DataFrame.from_dict(j[u'data'])
print( j[u'fields'] )
[u'date', u'energy', u'impact-e', u'lat', u'lat-dir', u'lon', u'lon-dir', u'alt', u'vel']
print( df.head() )
0    1      2     3     4     5     6     7     8
0  2019-12-06 10:19:57  4.6   0.15   3.3     S  37.7     W  19.5  None
1  2019-12-03 06:46:27  4.2   0.14   5.6     N  52.2     W  61.5  None
2  2019-11-28 20:30:54  2.7  0.095  35.7     N  31.7     W    35  13.0
3  2019-11-28 13:22:10  2.6  0.092  None  None  None  None  None  None
4  2019-11-28 11:55:02  2.5  0.089  22.1     S  25.7     E  22.5  24.7

我尝试过的代码行:

尝试使用df.apply()- 尽管通过我的搜索,我认为您不能以这种方式轻松引用两列......

df['lat'] = df['lat'].apply(lambda x: x * -1 if (df['lat-dir'][x] == 'S'))

for i, row in df.iterrows():
if (row['lat-dir'] == 'S'):
df['lat'][i].apply(lambda x: x*-1)

为此,我得到"numpy.float64"对象没有属性"应用"?


尝试使用屏蔽:

if( df['lon-dir'] == 'W'):
df['lon'] * -1

但坦率地说,我对下一步该怎么做很困惑。

编辑:

dfDate['lat'] = dfDate['lat'].apply(lambda row: row['lon'] * -1 , axis = 1 )

根据评论也尝试了这一点。

是的,通过以下任一方式:

A(使用矢量化掩码==未矢量化;.eq(...)是。对于矢量化表达式,请使用dfDate['lon-dir'].eq('W')。然后否定这些行上的"lon"列。

B(按行使用apply()dfDate['lon'] = dfDate.apply(lambda row: ..., axis=1)- 在您的 lambda 中根据值row['lon-dir']有选择地否定row['lon']-apply调用失败的原因是您需要应用于整个列/系列,而不是单个条目。所以:df['lat'].apply(lambda: ..., axis=1)

lat-dir/lon-dir本质上是符号列,您可以在读入它们时将它们转换为 +1/-1。

法典:

首先,您需要修复一些代码问题:

  1. 不要使用 u'..."记谱法。假设你使用的是Python 3.x,不需要u'...',文本现在在3.x中默认是Unicode。如果你没有使用Python 3.x,你真的应该现在切换,2.x将于2020年1月1日日落。
  2. 将 JSON 列名称传递到数据帧上,让您的生活变得轻松:
    • df.columns = j['fields']
  3. 通过将response.json()传递到pd.DataFrame.from_dict()中来读取JSON是一种痛苦;您的数据帧列成为字符串/"对象",而不是将浮点数转换为浮点数。理想情况下,出于这个和其他方便的原因,我们应该使用pandas.read_json(..., dtype=...)
  4. 您将需要转换数字列上的dtypes(例如字符串->浮点数(,并且还会自动将Python转换为None->pandas/numpynan(为了矢量化代码,我们将编写优雅地处理nan而不是不断抛出烦人的TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'(。你可以[用astype(...)pd.to_numeric()df.fillna(value=pd.np.nan, inplace=True)
  5. 实际上,由于下面列出的多种原因(例如,整数不断被强制恢复为浮点数(,这些 nan 条目将继续成为痛苦,因此您可能希望通过执行以下操作来删除或至少暂时忽略 nan 行
    • df2 = df.dropna(how='any', inplace=False)#可能与..., inplace=True无关.请注意,这会保留行索引,因此您始终可以在末尾将 df2 的结果插入回 df 中。阅读dropna文档,并弄清楚您想在什么确切时间点放弃nan。
    • 请注意,"vel"列实际上还有其他我们想忽略的nan,您需要弄清楚,或者暂时忽略它们:例如,做df2 = df[['date','energy','impact-e','lat','lat-dir','lon','lon-dir']].dropna(how='any', inplace=False)

溶液

  1. 几种将纬度/纬度-目录列转换为 +/-1 符号的方法:

    A1(如果你想要"正确"的,楠楠意识的方式,不会窒息楠......

df2['lat'] = df2['lat-dir'].map({'N': +1, 'S': -1})
df2['lon'] = df2['lon-dir'].map({'E': +1, 'W': -1})
A2) ...or a fast-and-dirty way:
(-1) ** df2['lat-dir'].eq('S')
(-1) ** df2['lon-dir'].eq('W')

B(但是您可以在一个逐行apply()函数中完成所有这些操作:

def fixup_latlon_signs(row):
row['lat'] = row['lat'] * (-1) ** (row['lat-dir'] == 'S')
row['lon'] = row['lon'] * (-1) ** (row['lon-dir'] == 'W')
return row
df2.apply(fixup_latlon_signs, axis=1)
# Then insert the non-NA rows we processed back into the parent dataframe:
df.update(df2)
# Strictly we can drop 'lat-dir','lon-dir' now...

最新更新