【问题标题】:Pandas how to not apply to whole column熊猫如何不适用于整列
【发布时间】:2018-05-03 14:47:45
【问题描述】:
self.df['Regular Price'] = self.df['Regular Price'].apply(
            lambda x: int(round(x)) if isinstance(
                x, (int, float)) else None
        )

只要在数据帧中遇到非数字值,上面的代码就会将 None 分配给字段 Regular Price 的每个值。我只想将None 分配给它的非数字值的那个单元格。

谢谢

【问题讨论】:

  • 我不知道我是否理解你的问题,但是你在寻找applymap 方法吗?
  • @Ivan applymap 适用于完整的数据框,或者我们可以将其应用于特定列?

标签: python pandas


【解决方案1】:

首先不可能将NaNs 与integers 一起返回,因为NaNs 在设计上是float。

如果mixed 类型为数字,strings 则您的解决方案有效:

df = pd.DataFrame({
    'Regular Price': ['a',1,2.3,'a',7],
    'B': list(range(5))
})
print (df)
   B Regular Price
0  0             a
1  1             1
2  2           2.3
3  3             a
4  4             7

df['Regular Price'] = df['Regular Price'].apply(
            lambda x: int(round(x)) if isinstance(
                x, (int, float)) else None
        )

print (df)
   B  Regular Price
0  0            NaN
1  1            1.0
2  2            2.0
3  3            NaN
4  4            7.0

但如果所有数据都是字符串,则需要 to_numeric 和 errors='coerce' 将非数字转换为 NaNs:

df = pd.DataFrame({
    'Regular Price': ['a','1','2.3','a','7'],
    'B': list(range(5))
})
print (df)
   B Regular Price
0  0             a
1  1             1
2  2           2.3
3  3             a
4  4             7

df['Regular Price'] = pd.to_numeric(df['Regular Price'], errors='coerce').round()
print (df)
   B  Regular Price
0  0            NaN
1  1            1.0
2  2            2.0
3  3            NaN
4  4            7.0

编辑:

我还需要删除浮点并仅使用int

可以将NaNs 转换为None 并转换为int:

df['Regular Price'] = pd.to_numeric(df['Regular Price'],
                                    errors='coerce').round()

df['Regular Price'] = np.where(df['Regular Price'].isnull(), 
                               None,
                               df['Regular Price'].fillna(0).astype(int))

print (df)
   B Regular Price
0  0          None
1  1             1
2  2             2
3  3          None
4  4             7


print (df['Regular Price'].apply(type))
0    <class 'NoneType'>
1         <class 'int'>
2         <class 'int'>
3    <class 'NoneType'>
4         <class 'int'>
Name: Regular Price, dtype: object

但它会降低性能,所以最好不要使用它。还应该有另一个问题 - soe 功能失败,所以最好是 floats 如果使用 NaNs:

在50k rows DataFrame 中测试diff 之类的函数:

df = pd.DataFrame({
    'Regular Price': ['a','1','2.3','a','7'],
    'B': list(range(5))
})
df = pd.concat([df]*10000).reset_index(drop=True)
print (df)

df['Regular Price'] = pd.to_numeric(df['Regular Price'], errors='coerce').round()

df['Regular Price1'] = np.where(df['Regular Price'].isnull(), 
                               None,
                               df['Regular Price'].fillna(0).astype(int))

In [252]: %timeit df['Regular Price2'] = df['Regular Price1'].diff()

TypeError: 不支持的操作数类型 -: 'int' 和 'NoneType'

In [274]: %timeit df['Regular Price3'] = df['Regular Price'].diff()
1000 loops, best of 3: 301 µs per loop

In [272]: %timeit df['Regular Price2'] = df['Regular Price1'] * 1000
100 loops, best of 3: 4.48 ms per loop

In [273]: %timeit df['Regular Price3'] = df['Regular Price'] * 1000
1000 loops, best of 3: 469 µs per loop

编辑:

df = pd.DataFrame({
    'Regular Price': ['a','1','2.3','a','7'],
    'B': list(range(5))
})
print (df)
   B Regular Price
0  0             a
1  1             1
2  2           2.3
3  3             a
4  4             7

df['Regular Price'] = pd.to_numeric(df['Regular Price'], errors='coerce').round()
print (df)
   B  Regular Price
0  0            NaN
1  1            1.0
2  2            2.0
3  3            NaN
4  4            7.0

首先可以逐列删除NaNs 行Regular Price,然后转换为int。

df1 = df.dropna(subset=['Regular Price']).copy()
df1['Regular Price']  = df1['Regular Price'].astype(int)
print (df1)
   B  Regular Price
1  1              1
2  2              2
4  4              7

处理您需要的内容,但不要更改索引。

#e.g. some process 
df1['Regular Price']  = df1['Regular Price'] * 100

最后一个combine_first - 它将NaN 添加到Regular Price 列。

df2 = df1.combine_first(df)
print (df2)
     B  Regular Price
0  0.0            NaN
1  1.0          100.0
2  2.0          200.0
3  3.0            NaN
4  4.0          700.0

【讨论】:

  • @Raheel Khan 这就是apply 和applymap 之间的区别。看看她stackoverflow.com/questions/19798153/…
  • 好的,如果转换成object 效果好吗?这有点hack,所以宁愿仔细测试。谢谢。
  • 不,这是第一步。但是integer 和NaNs 存在问题 - 而且它不是本机支持的,所以只有 hacky 解决方案。想法 - 可以改为 None 使用一些整数,如 -1 或 -1000 ?
  • 最好是测试一下。将np.where 中的None 更改为""。
  • 嗯,我知道了。是否可以先过滤NaNs,应用解决方案仅与ints 一起使用,最后添加NaNs?
猜你喜欢
  • 1970-01-01
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-30
  • 2014-05-11
  • 2020-10-24
相关资源
最近更新 更多