根据小数点后的值从 Pandas DataFrame 中删除行

Drop rows from Pandas DataFrame based on value after decimal

我有一个大 DF,带有值和名称。在以增量 0.1 插入值后,我想删除带有数字(例如 1111.123)的行,并仅保留带有 1111.0、1111.1、1111.2(或 1111.100...)

的行
Value Name
1111.1 Mark
1111.2 Mark
1111.234 Mark
1111.3 Mark
1111.346 Mark
1111.4 Mark

我试过 Series.str.split() 按字符串,但对于大于 1 GB 的 CSV 来说太慢了。我用

尝试过正则表达式
m = df['Value'].str.filter(regex='(\d*)\.(\d{3})')

但它 returns 空系列。

我试过的另一个选择是 math.modf,但 returns

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

这是代码本身:

import pandas as pd
from math import modf

df = pd.read_csv("file.csv")

split = ((df['Value'].apply(lambda x: modf(x)[0])) * 10).apply(lambda x: modf(x)[0])
target_value = 0 < split < 1
df1 = df.loc[split == target_value]
*some code to remove rows*

我期望的最终结果是:

Value Name
1111.1 Mark
1111.2 Mark
1111.3 Mark
1111.4 Mark

首先需要读取字符串等值,然后测试模式数字“.”最后一位数字:

df = pd.read_csv("file.csv", dtype={'Value':str})
df = df[df['Value'].str.match('\d+\.\d{1}$')]

另一种不转换为字符串的想法,但可能会出现浮点精度问题,例如 1111.100000000094894:

s = df['Value'] * 10
df = df[s.eq(s.astype(int))]
print (df)
    Value  Name
0  1111.1  Mark
1  1111.2  Mark
3  1111.3  Mark
5  1111.4  Mark

排除在点和末尾之间没有 1 作为单个数字或在点和末尾之间没有 0 的任何行。

df[(df['Value'].astype(str).str.contains('(?<=\.)[^0]$|(?<=\.)[1]$'))]



   Value  Name
0  1111.1  Mark
1  1111.2  Mark
3  1111.3  Mark
5  1111.4  Mark

根据您的评论让我们试试

        Value   Name
0  1111.100000   Mark
1  1111.200000   Mark
2  1111.230000   Mark
3  1111.300000   Mark
4  1111.346000   Mark
5  1111.400000   Mark
6  1111.100099  Added

输出

    Value  Name
0  1111.1  Mark
1  1111.2  Mark
3  1111.3  Mark
5  1111.4  Mark

如果您不想将浮点数转换为字符串,请使用这个简单的数学技巧来检查第一个数后是否有小数:

df[(df['Value']*10%1).eq(0)]

或者,您可以简单地检查倒数第二个字符是否为 .:

df[df['Value'].astype(str).str[-2].eq('.')]

输出:

    Value  Name
0  1111.1  Mark
1  1111.2  Mark
3  1111.3  Mark
5  1111.4  Mark

试试这个:

 df["value"] = df["value"].apply(lambda x: x - x % 0.1)