【问题标题】:how to select rows with float64 nan?如何使用 float64 nan 选择行?
【发布时间】:2018-11-06 17:00:44
【问题描述】:

我有一个来自 excel 的数据框,它在行中有几个 NaN。我想用另一个基线行替换值都是 NaN 的行。

原来的dataframe是这样的:

                    Country Name  Years  tariff1_1  tariff1_2  tariff1_3  
830                 Hungary       2004   9.540313   6.287314  13.098201   
831                 Hungary       2005   9.540789   6.281724  13.124401 
832                 Hungary       2006   NaN        NaN       NaN 
833                 Hungary       2007   NaN        NaN       NaN 
834                 eu            2005   8.55       5.7       11.4
835                 eu            2006   8.46       5.9       11.6
836                 eu            2007   8.56       5.3       11.9

因此,如果特定年份的匈牙利关税都是 NaN,则应根据确切年份将这一行替换为欧盟数据。

理想的结果是:

                    Country Name  Years  tariff1_1  tariff1_2  tariff1_3  
830                 Hungary       2004   9.540313   6.287314  13.098201   
831                 Hungary       2005   9.540789   6.281724  13.124401 
832                 Hungary       2006   8.46       5.9       11.6 
833                 Hungary       2007   8.56       5.3       11.9
834                 eu            2005   8.55       5.7       11.4
835                 eu            2006   8.46       5.9       11.6
836                 eu            2007   8.56       5.3       11.9

我查看了特定行 ('Hungary',2006) 中 NaN 的类型,它变成了 'float64'。结果是输入类型不支持 ufunc 'isnan',在我使用 np.isnan 之后,根据强制转换规则“安全”,输入无法安全地强制转换为任何支持的类型。

所以我采用了math.isnan。但是 它似乎没有在我的测试行中检测到 NaN

test=df.loc[(df['Country Name'] == 'Hungary') & (df['Years']== 2006)]

test.iloc[:,4]
Out[293]: 
832   NaN
Name: tariff1_3, dtype: float64

math.isnan(any(test))
Out[294]:False

np.isnan(any(test))
Out[295]:ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

这是我原来的台词。

 Eu=['Austria','Belgium','Curacao','Denmark','Finland','France','Germany']

 for country in Eu:
        for year in range(2001,2012)
            if math.isnan(all(df.loc[(df['Country Name'] == country) & (df['Years'] == year)])):
                df.loc[(df['Country Name'] == country) & (df['Years'] == year)]=df.loc[(df['Country Name'] == 'eu') & (df['Years'] == year)]

谢谢!

【问题讨论】:

  • 你不需要 math.isnan,pandas 有很多方法可以检测 NAN,例如 .isna、.isnull
  • 我有点好奇,你最后的工作代码是什么?因为df.loc[(df['Country Name'] == country) & (df['Years'] == year)]=df.loc[(df['Country Name'] == 'eu') & (df['Years'] == year)] 对我来说没有使用示例数据。
  • @jezrael 我的最终代码如下:df=df.set_index(['Country Name','Years']) for Country in Eu: for year in range(2001,2016): if df.loc[(Country,year), : ].isnull().values.all(): df.loc[(Country,year), : ]=imp.loc[('European Union',year),:] imp=imp.reset_index() 老实说,两个 FOR 循环似乎是多余的。 (对不起,我在换行时遇到了一些麻烦)

标签: python python-3.x pandas dataframe


【解决方案1】:

如果只需要转换 NaN 行:

print (df)
    Country Name  Years  tariff1_1  tariff1_2  tariff1_3
830      Hungary   2004   9.540313   6.287314  13.098201
831      Hungary   2005        NaN   6.281724  13.124401
832      Hungary   2006        NaN        NaN        NaN
833      Hungary   2007        NaN        NaN        NaN
834           eu   2005   8.550000   5.700000  11.400000
835           eu   2006   8.460000   5.900000  11.600000
836           eu   2007   8.560000   5.300000  11.900000

Eu=['Austria','Belgium','Curacao','Denmark','Finland','France','Germany','Hungary']

#all columns without specified in list
cols = df.columns.difference(['Country Name','Years'])
#eu DataFrame for repalce missing rows
eu = df[df['Country Name'] == 'eu'].drop('Country Name', 1).set_index('Years')
print (eu)
       tariff1_1  tariff1_2  tariff1_3
Years                                 
2005        8.55        5.7       11.4
2006        8.46        5.9       11.6
2007        8.56        5.3       11.9

#filter only Eu countries and all missing values with columns cols 
mask = df['Country Name'].isin(Eu) & df[cols].isnull().all(axis=1)

#for filtered rows replace missing rows by fillna 
df.loc[mask, cols] = pd.DataFrame(df[mask].set_index('Years')
                                          .drop('Country Name', 1).fillna(eu).values,
                                  index=df.index[mask], columns=cols)
print (df)
    Country Name  Years  tariff1_1  tariff1_2  tariff1_3
830      Hungary   2004   9.540313   6.287314  13.098201
831      Hungary   2005        NaN   6.281724  13.124401
832      Hungary   2006   8.460000   5.900000  11.600000
833      Hungary   2007   8.560000   5.300000  11.900000
834           eu   2005   8.550000   5.700000  11.400000
835           eu   2006   8.460000   5.900000  11.600000
836           eu   2007   8.560000   5.300000  11.900000

【讨论】:

  • 谢谢你,这真的很有帮助!!我使用 'set_index(['Country Name','Years'])' 和 '.isnull().values.all()' 来选择,而且还有两个 for 循环层,似乎太多余了。从你的帖子中学到了很多:)
  • @ZhouXing98 - 超级,很高兴能帮上忙!仔细检查您的数据,因为我认为您的解决方案是错误的。
  • @jezael 是的,我已经检查了结果,这里没有大问题。仍然感谢您的建议! :D
  • @ZhouXing98 - 超级担心输出错误。美好的一天!
【解决方案2】:

你可以试试:

df.isnull().values.any()

对于您的情况:

test.isnull().values.any()

【讨论】:

  • hmmm, 比较复杂,但是如果它对 OP 有好处,那么 ok
猜你喜欢
  • 1970-01-01
  • 2020-07-11
  • 2019-07-25
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 2020-10-06
相关资源
最近更新 更多