python - pandas 匹配两列并创建另一列

标签 python pandas numpy pivot pandas-groupby

我有一个包含 A 、B 、C 列的数据框。我想比较 B 和 C 列并创建两列,即 A-1(当前行年份 -1)和 A-2(当前行年份 -2)其中 A 是年份列。

示例:在 1971 年的数据框中,B 列有 apple 、 Orange C 列只有苹果,1970 年有 B-香蕉、苹果和 C-苹果。 现在,对于 1971 年的每一行,我们尝试生成 A-1(1970) 和 A-2(1969) 列的值。在 (A-1)1970 年,苹果在 B、C 列中都被捕获,因此我们将 1971 年的前两行标记为"is",然后将第三行标记为“否”,因为 1970 年没有橙色。

因此,对于每一行,我们考虑年份(例如 1971 年)并检查 B 和 C 值,并查看该特定 B 值是否也在 Year-1(1970)和 Year-2(1969)的 C 列中捕获,在这种情况下,它将是 nan,因为我们的数据框中没有任何 1969 的记录)并相应地标记它们。

数据框:

 A          B          C       D
1971       apple    apple      yes
1971       apple    apple      yes
1971       orange   nan        no
1970       banana   nan        no
1970       apple    apple      yes
1972       mango    mango      yes
1972       banana   banana     yes
1972       orange   orange     yes
1972       apple    apple      yes
1973       banana    nan       no
1973       mango     mango     yes
1973       apple     nan       no
1974       orange    nan       no

输出:

 A          B          C       A-1    A-2
1971       apple    apple      yes    nan
1971       apple    apple      yes    nan
1971       orange   nan        no     nan
1970       banana   nan        nan    nan
1970       apple    apple      nan    nan
1972       mango    mango      no     no 
1972       banana   banana     no     no
1972       orange   orange     no     no
1972       apple    apple      yes    yes
1973       banana    nan       yes    no
1973       mango     mango     yes    no
1973       apple     nan       yes    yes
1974       orange    nan       no     yes

我不明白,请帮我解决这个问题。

最佳答案

import numpy as np
import pandas as pd
nan = np.nan
df = pd.DataFrame({'A': [1971, 1971, 1971, 1970, 1970, 1972, 1972, 1972, 1972, 1973, 1973, 1973, 1974], 'B': ['apple', 'apple', 'orange', 'banana', 'apple', 'mango', 'banana', 'orange', 'apple', 'banana', 'mango', 'apple', 'orange'], 'C': ['apple', 'apple', nan, nan, 'apple', 'mango', 'banana', 'orange', 'apple', nan, 'mango', nan, nan]})

# add an index column to the DataFrame
df = df.reset_index()
df['BC'] = np.where(df['B'] == df['C'], df['B'], nan)
A_min = df['A'].min()


for i in [1, 2]:
    col = 'A-{}'.format(i)
    col2 = 'Y+{}'.format(i)
    df[col2] = df['A']+i
    # fill with nans
    df[col] = nan
    # place 'no' except where there is no data for the year A-i
    mask = df['A']-i >= A_min
    df.loc[mask, col] = 'no'

    # place 'yes' where 'A','B' columns match 'Y+i','BC' columns
    match = pd.merge(df[['A','B','index']], df[[col2, 'BC']],
                     left_on=['A','B'], right_on=[col2,'BC'])
    df.loc[match['index'], col] = 'yes'
    
df = df.drop(['index', 'BC', 'Y+1', 'Y+2'], axis=1)    
print(df)

产量

       A       B       C  A-1  A-2
0   1971   apple   apple  yes  NaN
1   1971   apple   apple  yes  NaN
2   1971  orange     NaN   no  NaN
3   1970  banana     NaN  NaN  NaN
4   1970   apple   apple  NaN  NaN
5   1972   mango   mango   no   no
6   1972  banana  banana   no   no
7   1972  orange  orange   no   no
8   1972   apple   apple  yes  yes
9   1973  banana     NaN  yes   no
10  1973   mango   mango  yes   no
11  1973   apple     NaN  yes  yes
12  1974  orange     NaN   no  yes
<小时/>

它是如何工作的:

首先,让我们向 DataFrame 添加一个索引列。稍后它的目的会变得更加清晰。 (请注意,我在这里假设您的 DataFrame 的原始索引具有唯一值。稍后我们将依赖该属性...)

df = df.reset_index()
#     index     A       B       C
# 0       0  1971   apple   apple
# 1       1  1971   apple   apple
# 2       2  1971  orange     NaN
# 3       3  1970  banana     NaN
# 4       4  1970   apple   apple
# 5       5  1972   mango   mango
# 6       6  1972  banana  banana
# 7       7  1972  orange  orange
# 8       8  1972   apple   apple
# 9       9  1973  banana     NaN
# 10     10  1973   mango   mango
# 11     11  1973   apple     NaN
# 12     12  1974  orange     NaN

因为我们想要识别具有特定值的行,这在 B 中是相同的C列,让我们创建一个BC等于 B 的列当BC相等,并且 NaN当他们不是时:

In [123]: df['BC'] = np.where(df['B'] == df['C'], df['B'], nan)
In [124]: df
Out[124]: 
    index     A       B       C      BC
0       0  1971   apple   apple   apple
1       1  1971   apple   apple   apple
2       2  1971  orange     NaN     NaN
3       3  1970  banana     NaN     NaN
4       4  1970   apple   apple   apple
5       5  1972   mango   mango   mango
6       6  1972  banana  banana  banana
7       7  1972  orange  orange  orange
8       8  1972   apple   apple   apple
9       9  1973  banana     NaN     NaN
10     10  1973   mango   mango   mango
11     11  1973   apple     NaN     NaN
12     12  1974  orange     NaN     NaN

现在,我们将匹配不同年份的行,因此让我们添加一列来确定我们有兴趣比较的年份。例如,我们希望比较 A 时的行。 1971 年的行数为 Y+1等于 1971 年:

In [125]: df['Y+1'] = df['A']+1; df
Out[125]: 
    index     A       B       C      BC   Y+1
0       0  1971   apple   apple   apple  1972
1       1  1971   apple   apple   apple  1972
2       2  1971  orange     NaN     NaN  1972
3       3  1970  banana     NaN     NaN  1971
4       4  1970   apple   apple   apple  1971
5       5  1972   mango   mango   mango  1973
6       6  1972  banana  banana  banana  1973
7       7  1972  orange  orange  orange  1973
8       8  1972   apple   apple   apple  1973
9       9  1973  banana     NaN     NaN  1974
10     10  1973   mango   mango   mango  1974
11     11  1973   apple     NaN     NaN  1974
12     12  1974  orange     NaN     NaN  1975

通过此设置,我们可以通过合并 df 来识别应标记为"is"的行与它自己, 匹配列AB带列Y+1BC :

In [127]: pd.merge(df[['A','B','index']], df[['Y+1', 'BC']], left_on=['A','B'], right_on=['Y+1','BC'])
Out[127]: 
      A       B  index   Y+1      BC
0  1971   apple      0  1971   apple
1  1971   apple      1  1971   apple
2  1972   apple      8  1972   apple
3  1972   apple      8  1972   apple
4  1973  banana      9  1973  banana
5  1973   mango     10  1973   mango
6  1973   apple     11  1973   apple

请注意 index列指示应包含 yes 的行索引在 A-1柱子。这就是使用df = df.reset_index()的目的多于。如果没有它,我们在合并时就会丢失原始索引。

关于python - pandas 匹配两列并创建另一列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54159234/

相关文章:

python - 如何从 bash 脚本访问 python 返回值

python - ImportError:无法从 'ModelFactory' 导入名称 'frlearn.base'

python - 调用 OpenCV 函数时原始 numpy 数组会发生什么?

python - 如何在 sqlalchemy 查询中选择文字值?

python - Pandas read_csv 多个文件

python - 在 Python 中处理 pandas DataFrames 列划分中的零

python - 合并后只保留第一个匹配的列的值,其余可以是 0.0

python - 使用带有浮点值的列表运算符 "in"

python - 将散点数据转换为误差条等于标准差的分箱数据

javascript - 我可以将 Node.js 包与 Django 一起使用吗?