我正在使用从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。
法典:
首先,您需要修复一些代码问题:
- 不要使用 u'..."记谱法。假设你使用的是Python 3.x,不需要u'...',文本现在在3.x中默认是Unicode。如果你没有使用Python 3.x,你真的应该现在切换,2.x将于2020年1月1日日落。
- 将 JSON 列名称传递到数据帧上,让您的生活变得轻松:
df.columns = j['fields']
- 通过将
response.json()
传递到pd.DataFrame.from_dict()
中来读取JSON是一种痛苦;您的数据帧列成为字符串/"对象",而不是将浮点数转换为浮点数。理想情况下,出于这个和其他方便的原因,我们应该使用pandas.read_json(..., dtype=...)
。 - 您将需要转换数字列上的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)
- 实际上,由于下面列出的多种原因(例如,整数不断被强制恢复为浮点数(,这些 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 符号的方法:
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...