根据小数点后的值从 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)
我有一个大 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)