删除包含混合 dtype 的 df 中的异常值
Removing outliers in a df containing mixed dtype
我正在处理一个包含数字列和字符串列的 pandas DataFrame(dtype 是 object
),我想删除包含异常值的行柱子。换句话说,检测每列中的异常值并删除相应的行。
我找到了两个解决方案,但都没有考虑到我的 df 不只包含数字,因此它们都会导致错误(我假设遇到字符串时)。
Way 1:
from scipy import stats
df[(np.abs(stats.zscore(df)) < 3).all(axis=1)]
returnsTypeError: unsupported operand type(s) for /: 'str' and 'int'
。
这就是为什么我猜错误是由 df 混合数据类型引起的。
for col in df.columns:
lower = df[col].quantile(0.05)
upper = df[col].quantile(0.95)
df = df[col].clip(lower=lower, upper=upper)
returns KeyError
回溯:
File omissis, in Class.remove_outliers(self, df)
423 def remove_outliers(self, df):
424 for col in df.columns:
--> 425 lower = df[col].quantile(0.05)
426 upper = df[col].quantile(0.95)
427 df = df[col].clip(lower=lower, upper=upper)
File omissis, in Series.__getitem__(self, key)
955 return self._values[key]
957 elif key_is_scalar:
--> 958 return self._get_value(key)
960 if is_hashable(key):
961 # Otherwise index.get_value will raise InvalidIndexError
962 try:
963 # For labels that don't resolve as scalars like tuples and frozensets
File omissis, in Series._get_value(self, label, takeable)
1066 return self._values[label]
1068 # Similar to Index.get_value, but we do not fall back to positional
-> 1069 loc = self.index.get_loc(label)
1070 return self.index._get_values_for_loc(self, loc, label)
File omissis, in RangeIndex.get_loc(self, key, method, tolerance)
387 raise KeyError(key) from err
388 self._check_indexing_error(key)
--> 389 raise KeyError(key)
390 return super().get_loc(key, method=method, tolerance=tolerance)
KeyError: 'colname'
你会如何解决这个问题?
编辑:想法是跳过非数字列,忽略它们。
我会将问题分成几个阶段:
首先,确定要执行离群值删除的(数字)列。
Reference
newdf = df.select_dtypes(include=np.number)
现在对 newdf
的行执行任何 filtering/outlier 删除操作。之后,newdf
应该只包含您希望保留的行。
然后只保留 df
那些索引在 newdf
中的行。
df = df[df.index.isin(newdf.index)]
@Ipounng 在copy-paste 中的解决方案现成代码:
def remove_outliers(df):
newdf = df.select_dtypes(include=np.number)
newdf = newdf[(np.abs(stats.zscore(newdf)) < 3).all(axis=1)]
df = df[df.index.isin(newdf.index)]
return df
除了@lpounng 解决方案。对于分类变量,您不能使用 zscore,但您可以将低值 class 视为异常值。您可以为值计数设置阈值。
玩具数据集示例:
import random
import pandas as pd
colors = []
for i in range(100):
colors.append(random.choices(['yellow','white', 'red'], weights = [10, 1, 2])[0])
df = pd.DataFrame(colors, columns=['colors'])
我随机生成了一个包含黄色、白色和红色分类值的列,权重为 10,1,2。
使用 value_count()
pandas 方法,您可以计算列中唯一类别的计数
df['colors'].value_counts()
>>> yellow 68
red 20
white 12
Name: colors, dtype: int64
现在您可以设置一个阈值并删除人口稀少的类别,例如美国白人。
我正在处理一个包含数字列和字符串列的 pandas DataFrame(dtype 是 object
),我想删除包含异常值的行柱子。换句话说,检测每列中的异常值并删除相应的行。
我找到了两个解决方案,但都没有考虑到我的 df 不只包含数字,因此它们都会导致错误(我假设遇到字符串时)。
Way 1:
from scipy import stats
df[(np.abs(stats.zscore(df)) < 3).all(axis=1)]
returnsTypeError: unsupported operand type(s) for /: 'str' and 'int'
。
这就是为什么我猜错误是由 df 混合数据类型引起的。
for col in df.columns:
lower = df[col].quantile(0.05)
upper = df[col].quantile(0.95)
df = df[col].clip(lower=lower, upper=upper)
returns KeyError
回溯:
File omissis, in Class.remove_outliers(self, df)
423 def remove_outliers(self, df):
424 for col in df.columns:
--> 425 lower = df[col].quantile(0.05)
426 upper = df[col].quantile(0.95)
427 df = df[col].clip(lower=lower, upper=upper)
File omissis, in Series.__getitem__(self, key)
955 return self._values[key]
957 elif key_is_scalar:
--> 958 return self._get_value(key)
960 if is_hashable(key):
961 # Otherwise index.get_value will raise InvalidIndexError
962 try:
963 # For labels that don't resolve as scalars like tuples and frozensets
File omissis, in Series._get_value(self, label, takeable)
1066 return self._values[label]
1068 # Similar to Index.get_value, but we do not fall back to positional
-> 1069 loc = self.index.get_loc(label)
1070 return self.index._get_values_for_loc(self, loc, label)
File omissis, in RangeIndex.get_loc(self, key, method, tolerance)
387 raise KeyError(key) from err
388 self._check_indexing_error(key)
--> 389 raise KeyError(key)
390 return super().get_loc(key, method=method, tolerance=tolerance)
KeyError: 'colname'
你会如何解决这个问题?
编辑:想法是跳过非数字列,忽略它们。
我会将问题分成几个阶段:
首先,确定要执行离群值删除的(数字)列。 Reference
newdf = df.select_dtypes(include=np.number)
现在对 newdf
的行执行任何 filtering/outlier 删除操作。之后,newdf
应该只包含您希望保留的行。
然后只保留 df
那些索引在 newdf
中的行。
df = df[df.index.isin(newdf.index)]
@Ipounng 在copy-paste 中的解决方案现成代码:
def remove_outliers(df):
newdf = df.select_dtypes(include=np.number)
newdf = newdf[(np.abs(stats.zscore(newdf)) < 3).all(axis=1)]
df = df[df.index.isin(newdf.index)]
return df
除了@lpounng 解决方案。对于分类变量,您不能使用 zscore,但您可以将低值 class 视为异常值。您可以为值计数设置阈值。
玩具数据集示例:
import random
import pandas as pd
colors = []
for i in range(100):
colors.append(random.choices(['yellow','white', 'red'], weights = [10, 1, 2])[0])
df = pd.DataFrame(colors, columns=['colors'])
我随机生成了一个包含黄色、白色和红色分类值的列,权重为 10,1,2。
使用 value_count()
pandas 方法,您可以计算列中唯一类别的计数
df['colors'].value_counts()
>>> yellow 68
red 20
white 12
Name: colors, dtype: int64
现在您可以设置一个阈值并删除人口稀少的类别,例如美国白人。