python - 根据另一列的掩码修改 Pandas 数据框列的符号?

标签 python pandas dataframe apply signed

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

  • lat/lon 数据只有正值
  • 它们的方向(北/南和东/西)位于不同的列中,称为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 )

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

最佳答案

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

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

    关于python - 根据另一列的掩码修改 Pandas 数据框列的符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59232584/

    相关文章:

    python - 忽略数据框中的 NaN

    python - 基于 python 3.x 列表中项目的条件 if 语句

    python - 在 Python 中有效地按键选择字典项目

    python - Python中dict对象的联合

    python - 输入 : type hinting when function returns tuple with unpacked list

    python - 将包含 NaN 的 Pandas 列转换为 dtype `int`

    python - Pandas:根据列上的条件生成多个条形图

    python - 如何显示多行而不是一行?

    Python:使用列值聚合行并为每个键删除一行

    python - 取 pandas 中两个时间戳范围条件的交集