如何将熊猫数据框中的负数替换为零

我想知道是否有办法将所有数据框架的负数替换为零?

216692 次浏览

如果所有的列都是数字,那么可以使用布尔索引:

In [1]: import pandas as pd


In [2]: df = pd.DataFrame({'a': [0, -1, 2], 'b': [-3, 2, 1]})


In [3]: df
Out[3]:
a  b
0  0 -3
1 -1  2
2  2  1


In [4]: df[df < 0] = 0


In [5]: df
Out[5]:
a  b
0  0  0
1  0  2
2  2  1

对于更一般的情况,这个答案显示了私有方法 _get_numeric_data:

In [1]: import pandas as pd


In [2]: df = pd.DataFrame({'a': [0, -1, 2], 'b': [-3, 2, 1],
'c': ['foo', 'goo', 'bar']})


In [3]: df
Out[3]:
a  b    c
0  0 -3  foo
1 -1  2  goo
2  2  1  bar


In [4]: num = df._get_numeric_data()


In [5]: num[num < 0] = 0


In [6]: df
Out[6]:
a  b    c
0  0  0  foo
1  0  2  goo
2  2  1  bar

With timedelta type, boolean indexing seems to work on separate columns, but not on the whole dataframe. So you can do:

In [1]: import pandas as pd


In [2]: df = pd.DataFrame({'a': pd.to_timedelta([0, -1, 2], 'd'),
...:                    'b': pd.to_timedelta([-3, 2, 1], 'd')})


In [3]: df
Out[3]:
a       b
0  0 days -3 days
1 -1 days  2 days
2  2 days  1 days


In [4]: for k, v in df.iteritems():
...:     v[v < 0] = 0
...:


In [5]: df
Out[5]:
a      b
0 0 days 0 days
1 0 days 2 days
2 2 days 1 days

更新: pd.Timedelta的比较适用于整个 DataFrame:

In [1]: import pandas as pd


In [2]: df = pd.DataFrame({'a': pd.to_timedelta([0, -1, 2], 'd'),
...:                    'b': pd.to_timedelta([-3, 2, 1], 'd')})


In [3]: df[df < pd.Timedelta(0)] = 0


In [4]: df
Out[4]:
a      b
0 0 days 0 days
1 0 days 2 days
2 2 days 1 days

也许你可以这样使用 pandas.where(args):

data_frame = data_frame.where(data_frame < 0, 0)

另一种简洁的方法是 熊猫,数据框架,剪辑

例如:

import pandas as pd


In [20]: df = pd.DataFrame({'a': [-1, 100, -2]})


In [21]: df
Out[21]:
a
0   -1
1  100
2   -2


In [22]: df.clip(lower=0)
Out[22]:
a
0    0
1  100
2    0

如果您处理的是大型 df (在我的例子中是40m x 700) ,那么通过对列进行类似下面这样的迭代,它可以更快地工作,并且具有更强的内存理解能力。

for col in df.columns:
df[col][df[col] < 0] = 0

我发现另一个有用的干净选项是 熊猫,数据框架,面具,它将“替换条件为真的值”

创建数据框架:

In [2]: import pandas as pd


In [3]: df = pd.DataFrame({'a': [0, -1, 2], 'b': [-3, 2, 1]})


In [4]: df
Out[4]:
a  b
0  0 -3
1 -1  2
2  2  1

用0代替负数:

In [5]: df.mask(df < 0, 0)
Out[5]:
a  b
0  0  0
1  0  2
2  2  1


或者,用 NaN 代替负数,这是我经常需要的:

In [7]: df.mask(df < 0)
Out[7]:
a    b
0  0.0  NaN
1  NaN  2.0
2  2.0  1.0

具有 lambda 函数

df['column'] = df['column'].apply(lambda x : x if x > 0 else 0)

现有答案稍作修改。

Let's identify all the numeric columns and create a dataframe with all numeric values. 然后在新的数据帧中用 NaN 替换负值

df_numeric = df.select_dtypes(include=[np.number])
df_numeric = df_numeric.where(lambda x: x > 0, np.nan)

现在,删除主数据框架中处理负值的列,然后将新列值连接到主数据框架

numeric_cols = df_numeric.columns.values
df = df.drop(columns=numeric_cols)
df = pd.concat([df, df_numeric], axis = 1)

If you have a dataset of mixed data types, also consider moving the non-numerics to the index, updating the data, then removing the index:

df = pd.DataFrame({'a': [0, -1, 2], 'b': [-3, 2, 1],
'c': ['foo', 'goo', 'bar']})
df = df.set_index('c')
df[df < 0] = 0
df = df.reset_index()

由于某些原因,使用 _get_numeric_data()的方法对我不起作用。