使用 pandas 比较两列
- 2025-02-17 09:25:00
- admin 原创
- 83
问题描述:
以此为起点:
a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
看起来像
one two three
0 10 1.2 4.2
1 15 70 0.03
2 8 5 0
我想使用类似if
熊猫内的语句的东西。
if df['one'] >= df['two'] and df['one'] <= df['three']:
df['que'] = df['one']
基本上,通过if
语句检查每一行来创建一个新列。
文档说可以使用.all
,但没有例子......
解决方案 1:
你可以使用np.where。如果cond
是布尔数组,并且A
和B
是数组,那么
C = np.where(cond, A, B)
定义 C 等于A
其中cond
为 True,B
其中cond
为 False。
import numpy as np
import pandas as pd
a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
df['que'] = np.where((df['one'] >= df['two']) & (df['one'] <= df['three'])
, df['one'], np.nan)
产量
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 NaN
2 8 5 0 NaN
如果你有多个条件,那么你可以改用np.select。例如,如果你想在 时df['que']
相等,那么df['two']
`df['one'] < df['two']`
conditions = [
(df['one'] >= df['two']) & (df['one'] <= df['three']),
df['one'] < df['two']]
choices = [df['one'], df['two']]
df['que'] = np.select(conditions, choices, default=np.nan)
产量
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 70
2 8 5 0 NaN
如果我们可以假设df['one'] >= df['two']
当df['one'] < df['two']
为假,那么条件和选择就可以简化为
conditions = [
df['one'] < df['two'],
df['one'] <= df['three']]
choices = [df['two'], df['one']]
df['one']
(如果或包含 NaN,则该假设可能不成立df['two']
。)
注意
a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
定义一个带有字符串值的 DataFrame。由于它们看起来是数字,因此最好将这些字符串转换为浮点数:
df2 = df.astype(float)
但这会改变结果,因为字符串是逐个字符进行比较,而浮点数是按数字进行比较。
In [61]: '10' <= '4.2'
Out[61]: True
In [62]: 10 <= 4.2
Out[62]: False
解决方案 2:
您可以用来.equals
比较两列:
df['col1'].equals(df['col2'])
或者比较两个数据框:
df1.equals(df2)
如果它们相等,该语句将返回True
,否则False
。
解决方案 3:
您可以使用apply()并做类似的事情
df['que'] = df.apply(lambda x : x['one'] if x['one'] >= x['two'] and x['one'] <= x['three'] else "", axis=1)
或者如果你不想使用 lambda
def que(x):
if x['one'] >= x['two'] and x['one'] <= x['three']:
return x['one']
return ''
df['que'] = df.apply(que, axis=1)
解决方案 4:
一种方法是使用布尔系列对列进行索引df['one']
。这将为您提供一个新列,其中的True
条目与同一行具有相同的值,df['one']
并且False
值为NaN
。
布尔级数只是由您的if
陈述给出的(尽管有必要使用&
而不是and
):
>>> df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])]
>>> df
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 NaN
2 8 5 0 NaN
如果要将NaN
值替换为其他值,可以使用fillna
新列上的方法que
。我0
在这里使用了 而不是空字符串:
>>> df['que'] = df['que'].fillna(0)
>>> df
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 0
2 8 5 0 0
解决方案 5:
将每个单独的条件括在括号中,然后使用&
运算符组合条件:
df.loc[(df['one'] >= df['two']) & (df['one'] <= df['three']), 'que'] = df['one']
您只需使用~
(“not”运算符)反转匹配即可填充不匹配的行:
df.loc[~ ((df['one'] >= df['two']) & (df['one'] <= df['three'])), 'que'] = ''
您需要使用&
and~
而不是and
and,not
因为&
and~
运算符是逐个元素工作的。
最终结果:
df
Out[8]:
one two three que
0 10 1.2 4.2 10
1 15 70 0.03
2 8 5 0
解决方案 6:
我想为那些试图比较两列中值的相等性NaN
并False
在两个值都相等时得到结果的人添加这个答案NaN
。 根据定义,NaN
!= NaN
(参见:numpy.isnan(value) 与 value == numpy.nan 不同? )。
如果希望NaN
返回两个比较结果True
,可以使用:
df['compare'] = (df["col_1"] == df["col_2"]) | (df["col_1"].isna() & df["col_2"].isna())
解决方案 7:
使用 lambda 表达式:
df[df.apply(lambda x: x['col1'] != x['col2'], axis = 1)]
解决方案 8:
np.select
如果您需要从数据框中检查多个条件并在不同的列中输出特定的选择,请使用
conditions=[(condition1),(condition2)]
choices=["choice1","chocie2"]
df["new column"]=np.select=(condtion,choice,default=)
注意:条件数和选择数应匹配,如果两个不同条件有相同的选择,则重复选择中的文本。
解决方案 9:
您可以使用该方法where
:
df['que'] = df['one'].where((df['one'] >= df['two']) & (df['one'] <= df['three']))
或方法eval
:
df['que'] = df.loc[df.eval('(one >= two) & (two <= three)'), 'one']
结果:
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 NaN
2 8 5 0 NaN
解决方案 10:
我认为最接近 OP 直觉的是内联 if 语句:
df['que'] = (df['one'] if ((df['one'] >= df['two']) and (df['one'] <= df['three']))
解决方案 11:
如果您要比较两个数据框列中的值,则可以使用eq()
:
df['one'].eq(df['two'])
或者eval()
df.eval("one == two")
如果您想将其简化为单个布尔值,请调用all()
结果:
df['one'].eq(df['two']).all()
# or
df.eval("one == two").all()
这是一个比 更“稳健”的检查,equals()
因为要equals()
返回 True,列的 dtype 也必须匹配。因此,如果一列是 dtypeint
而另一列是 dtype float
,equals()
即使值相同,也会返回 False,而eq().all()
/eval().all()
只是按元素比较列。
如果您的列包含 NaN 值,请使用以下命令(利用以下事实NaN != NaN
):
df.eval("one == two or one != one").all()
对于OP的具体问题,由于模式是“A <B和B <C”,因此您可以使用between()
:
cond = df['one'].between(df['two'], df['three'])
df['que'] = np.where(cond, df['one'], np.nan)
解决方案 12:
详细说明@ccook5760 的答案
您可以将 .equals 用于列或整个数据框。
df['col1'].equals(df['col2'])
如果它们相等,该语句将返回 True,否则返回 False。
为了验证相等性,列必须以相同的顺序包含相同的值,并且它们的索引也必须相同。
如果您想要检查两个不同数据框中的两列是否相等,其中值的顺序并不重要并且可能会有所不同,您可以先对值进行排序。
重置系列的索引也很重要,以便可以仅根据值来验证相等性。
以下是一种方法:
df1['col1'].sort_values().reset_index(drop=True).equals(df2['col2'].sort_values().reset_index(drop=True))
同样的方法,但更易读:
s1 = df1['col1'].sort_values().reset_index(drop=True)
s2 = df2['col2'].sort_values().reset_index(drop=True)
s1.equals(s2)
解决方案 13:
如果您的列包含相同顺序的相同值并且它们是数字,则使用相等,否则使用 .equals 方法
col1 包含:58.1.2、29.2.4 col2 包含:58.1.2、28.2.4
语法:
mydf['processedRecords'] = (mydf['col1'] == mydf['col2'])
因此当匹配时,您将获得 True;当不匹配时,您将获得 False
但值是非数字,请使用 .equals 方法
语法:
mydf['processedRecords'] = mydf['col1'].equals(mydf['col2'])
扫码咨询,免费领取项目管理大礼包!