【问题标题】:Conditional replace comma or spaces in number string in Pandas DataFrame column without a loop有条件地替换 Pandas DataFrame 列中数字字符串中的逗号或空格,无需循环
【发布时间】:2020-07-18 16:20:01
【问题描述】:

有时我的 DataFrame 中的字符串数字中有逗号,表示十进制或标记千位,有些则没有。数据框是我通过 API 收到的价格格式范围的一个示例,并且取决于货币。这些是价格,小数点始终为 2。所以我需要将字符串价格输出到浮点数中,这样我就可以将它们相加或将它们分离到其他数据框中或使用它们来绘制图表。我已经创建了一个循环来替换它们,但是没有循环有没有更快的方法来做到这一点?

我的DataFrame和工作循环如下:

data = {'amount': ['7,99', '6,99', '9.99', '-6,99', '1,000.00']}
df = pd.DataFrame(data)

fees = []
sales = []

for items in df['amount']:
    if items[-7:-6] == ',':
        items = float(items.replace(',', '').replace(' ',''))
    if items[-3:-2] == ',':
        items = float(items.replace(',', '.').replace(' ',''))
    items = float(items)
    if items <= 0:
        fees.append(items)
    else:
        sales.append(items)

我试图在没有循环的情况下执行此操作,但似乎无法找出我出错的地方。

df["amount"] = np.where((df['amount'][-7:-6] == ','),
                       df["amount"][-7:-6].str.replace(',', '').replace(' ',''),
                       df["amount"])

df["amount"] = np.where((df['amount'][-3:-2] == ','),
                       df["amount"][-3:-2].str.replace(',', '').replace(' ',''),
                       df["amount"])

任何帮助将不胜感激。提前谢谢你

【问题讨论】:

  • 你的预期输出是什么?
  • 好问题是这些错误的数字表示是从哪里来的。您可以尝试在数据框中修复它,但是您将如何猜测字符串 '1,234' 是否是整数值 @987654324 @(逗号作为千位分隔符)还是小数1.234(逗号作为小数分隔符)?
  • 感谢 cmets 并为我没有解释这些数字的来源表示歉意。这些是价格,小数点始终为 2。所以我需要将字符串价格输出为浮点数,这样我就可以将它们相加或将它们分开以用于其他数据帧或将它们绘制成图表。

标签: python pandas dataframe replace conditional-statements


【解决方案1】:

您可以使用 lambdas 代替 numpy:

lambda1 = lambda items: float(str(items).replace(',', '').replace(' ','')) if str(items)[-7:-6] == ',' else items
lambda2 = lambda items: float(str(items).replace(',', '.').replace(' ','')) if str(items)[-3:-2] == ',' else items
to_float = lambda items: float(items)

df['amount_clean'] = df["amount"].map(lambda1).map(lambda2).map(to_float) 

================================================ ============================

编辑:什么是 lambdas

在 python 中,lambda 函数是具有单个表达式的小型匿名函数(请参阅https://www.w3schools.com/python/python_lambda.asp

条件示例:

lambda x: x + 1 if x < 0 else x

这相当于:

def my_lambda_function(x):
    if x < 0:
        return x + 1
    else:
        return x

当通过 map 函数传递到 pandas 数据框的列时,lambda 表达式将应用于该列的每一行中的值。

希望这会有所帮助!

【讨论】:

  • 太好了,非常感谢。我刚刚开始编码,所以我需要熟悉 lambda,以便了解它是如何工作的。欣赏答案。
【解决方案2】:

由于您提到最后两位数字是小数点,因此需要将 ',' 替换为 '.' 以使其成为 float,但您也有一些像 1,000.00 这样的值,如果',''.' 替换,因此您可以使用 regex 来确定要替换的值:

data = {'amount': ['7,99', '6,99', '9.99', '-6,99', '1,000.00']}
df = pd.DataFrame(data)
df

首先regex 将匹配所有带有',' 和两个小数点的字符串,然后替换函数将用'.' 和捕获的值(99 from ,99)替换匹配项

df['amount'] = df['amount'].str.replace(r'(,)(\d{2}$)',r'.\2') 
# here `r'.\2'`is second `captured group` in `regex`

然后要将1,000.00 转换为float,我们将',' 替换为空白

df['amount'] = df['amount'].str.replace(',','')

然后将数据类型转换为float

df['amount'] = df['amount'].astype(float)

print(df)
    amount
0   799.00
1   699.00
2     9.99
3  -699.00
4  1000.00

【讨论】:

  • 太好了,非常感谢您的回答,非常感谢。我是新手,所以我需要了解正则表达式。
  • This 有很大帮助
【解决方案3】:

尝试使用拆分和连接,

df.amount.str.split(',').str.join('').astype(float)

输出

0     799.00
1     699.00
2       9.99
3    -699.00
4    1000.00
Name: amount, dtype: float64

【讨论】:

  • 感谢您的帮助。我的问题是并非所有的逗号都是小数。欧元的价格通常以逗号表示小数,但有时其他货币的千位也用逗号标记。所有价格都有 2 位小数,因此最后 2 位数字始终为小数。
  • 好的。这似乎非常适合您的情况。
猜你喜欢
  • 2019-04-08
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 2017-11-18
  • 2020-04-21
相关资源
最近更新 更多