如何将 Pandas 数据框中的负数替换为零
Posted
技术标签:
【中文标题】如何将 Pandas 数据框中的负数替换为零【英文标题】:How to replace negative numbers in Pandas Data Frame by zero 【发布时间】:2015-03-01 18:48:56 【问题描述】:我想知道是否有办法将所有 DataFrame 负数替换为零?
【问题讨论】:
另外,我相信你的第二行应该是num[num < 0] = 0
【参考方案1】:
如果所有列都是数字,则可以使用布尔索引:
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
对于更一般的情况,this answer 显示私有方法 _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
对于timedelta
类型,布尔索引似乎适用于单独的列,但不适用于整个数据框。所以你可以这样做:
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
【讨论】:
【参考方案2】:也许你可以像这样使用pandas.where(args)
:
data_frame = data_frame.where(data_frame < 0, 0)
【讨论】:
【参考方案3】:另一种简洁的方法是pandas.DataFrame.clip。
例如:
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.clip_lower(0)
。
【讨论】:
这是我一直在寻找的内联解决方案!谢谢! 如果您只想在特定列上应用clip
,您可以使用df['col_name'] = df['col_name'].clip(lower=0)
clip_lower
一直是deprecated 所以宁愿坚持df.clip(lower=0)
这似乎是最快的方法【参考方案4】:
如果您正在处理较大的 df(在我的情况下为 40m x 700),它可以通过在列上进行迭代来更快地工作并且节省内存。
for col in df.columns:
df[col][df[col] < 0] = 0
【讨论】:
当您执行此操作时,您会收到 试图在数据帧的切片副本上设置值 警告 也许使用 .copy() 会避免它【参考方案5】:我发现另一个有用的干净选项是pandas.DataFrame.mask,它将“替换条件为真的值”。
创建数据框:
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
【讨论】:
.mask()
就像它得到的吻一样!【参考方案6】:
带 lambda 函数
df['column'] = df['column'].apply(lambda x : x if x > 0 else 0)
【讨论】:
【参考方案7】:对现有答案稍作修改。
让我们识别所有数值列并创建一个包含所有数值的数据框。 然后在新数据框中用 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)
【讨论】:
以上是关于如何将 Pandas 数据框中的负数替换为零的主要内容,如果未能解决你的问题,请参考以下文章