我想知道是否有一种方法可以用0替换所有DataFrame中的负数?
我想知道是否有一种方法可以用0替换所有DataFrame中的负数?
如果您的所有列都是数值型的,您可以使用布尔索引:
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
使用 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
另一种简洁的方法是使用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
clip
,可以这样做:df['col_name'] = df['col_name'].clip(lower=0)
。 - gies0rclip_lower
已经被弃用,因此最好使用df.clip(lower=0)
。请注意,这两个函数的作用相同,都是将DataFrame或Series中的值限制在下限之上(本例中为0)。 - Sally Levesque我发现另一个干净的选项是 pandas.DataFrame.mask,它可以“替换满足条件的值”。
创建DataFrame:
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()
就是最简单易懂的! - mirekphd或许你可以这样使用 pandas.where(args)
:
data_frame = data_frame.where(data_frame < 0, 0)
使用Lambda函数
df['column'] = df['column'].apply(lambda x : x if x > 0 else 0)
如果您正在处理一个大的数据框(例如我的情况是40m x 700),通过迭代列来处理会更快速和更省内存,可以使用以下代码:
for col in df.columns:
df[col][df[col] < 0] = 0
稍作修改的答案如下:
让我们识别所有数值列,并创建一个包含所有数值的数据框。然后在新数据框中将负值替换为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)
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()
方法的方式出了一些问题,对我来说无效。
num[num < 0] = 0
。 - hlin117