根据另一列的遮罩修改Pandas数据框的列的符号?

时间:2019-12-08 05:03:46

标签: python pandas dataframe apply signed

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

  • lat / lon数据仅具有正值
  • 他们的方向(N / S和E / W)在不同的列中,称为lat-dir / lon-dir
  • 数据框架如下。
  • 现在我要:
  • 如果“ lat-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”对象没有属性“ apply”?


尝试使用遮罩:

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

但是坦率地说,我对下一步使用口罩感到困惑。

编辑:

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

根据评论也尝试过此操作。

1 个答案:

答案 0 :(得分:0)

是,通过以下任一方式:

A)使用矢量蒙版==未向量化; .eq(...)是。对于矢量化表达式,请使用dfDate['lon-dir'].eq('W')。然后在这些行上取反“ lon”列。

B)使用apply()dfDate['lon'] = dfDate.apply(lambda row: ..., axis=1)  -并在您的lambda中根据值row['lon']有选择地取反row['lon-dir']  -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,则应该立即切换,因为2020年1月1日将退出2.x。
  2. 将JSON列名称传递到数据框,让您的生活变得轻松:
    • df.columns = j['fields']
  3. 通过将response.json()传递到pd.DataFrame.from_dict()来读取JSON是很痛苦的;您的数据框列将变为字符串/“对象”,而不是将浮点数转换为浮点数。出于这个原因和其他方便原因,理想情况下,我们应该使用pandas.read_json(..., dtype=...)
  4. 您将要转换数字类型上的dtypes (例如,字符串-> float),这还将自动转换Python None-> pandas / numpy {{1 }}(为实现矢量化代码,我们将编写优美地处理nan而不是不断抛出烦人的nan的代码)。您可以[使用TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'astype(...)pd.to_numeric()
  5. 进行此操作
  6. 由于下面列出的多种原因,这些nan条目确实会很痛苦(例如,整数不断被强制返回浮点数),因此您可能想要删除或至少暂时忽略nan行< / strong>:
    • df.fillna(value=pd.np.nan, inplace=True)#可能不与df2 = df.dropna(how='any', inplace=False)一起使用。请注意,这将保留行索引,因此您始终可以将df2的处理结果最后插入到df中。阅读..., inplace=True文档,找出要删除nan的确切点。
    • 请注意,“ vel”列实际上还有其他我们要忽略的nan,您需要弄清楚这一点,或者现在就忽略它们:例如做dropna

解决方案

  1. 几种将lat / lon-dir列转换为+/- 1号的方法:

    A1)如果您想要“正确”的,可识别nan的方式,而不会阻塞nans ...

df2 = df[['date','energy','impact-e','lat','lat-dir','lon','lon-dir']].dropna(how='any', inplace=False)
    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:

B)但是您可以在一排 (-1) ** df2['lat-dir'].eq('S') (-1) ** df2['lon-dir'].eq('W') 函数中完成所有操作:

apply()