【问题标题】:pandas match two columns and create another column熊猫匹配两列并创建另一列
【发布时间】:2019-01-12 11:40:52
【问题描述】:

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

示例:在 1971 年的数据框中,B 列有 apple 、 orange C 列只有苹果,1970 年有 B-banana、apple 和 C-apple。 现在,对于 1971 年的每一行,我们尝试为 A-1(1970)、A-2(1969) 列生成值。在 (A-1)1970 年,苹果在 B、C 列中都被捕获,所以我们将 1971 年的前两行标记为“是”,然后将第三行标记为“否”,因为 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

我想不通,请帮助我。

【问题讨论】:

  • 好的,我马上编辑这个问题
  • @unutbu ,请查看已编辑的问题并提供解决方案
  • 我对你的最后一句话有点困惑,“所以对于每一行,我们都会考虑年份并检查 B 值......”。您的意思是说“所以对于每一行,我们都会考虑年份并检查B 和C 值......”?换句话说,yes 值是否表示 B 和 C 值都存在于相应年份?
  • 是的,我的错误我会改正句子,还有一件事你应该清楚的是,是的值表示对应的年份 -1 和对应的年份 -2 都存在 B 和 C 值跨度>
  • 我认为您给出的示例还没有回答所有场景组合。你能再改变几行例子吗?

标签: python pandas numpy pivot pandas-groupby


【解决方案1】:
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

由于我们想在BC 列中识别具有特定值相同 的行,所以让我们创建一个等于BBCBC 相等时,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 与其自身合并来识别应标记为“是”的行, 将列 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 列表示在A-1 列中应包含yes 的行索引。这就是上面使用df = df.reset_index() 的目的。没有它,我们合并时会丢失原始索引。

【讨论】:

  • 感谢您的回复,我会查看您的解决方案,我已经编辑了问题以涵盖所有场景。如果您想要查看,请检查一次
【解决方案2】:

这是解决您问题的代码:-

import pandas as pd
import csv


colnames=['A','B','C']
df=pd.read_csv("file1.txt",header=None,delim_whitespace=True)
df.columns=colnames
#print(df.head())


# Below the lines of Code for subset extract in pandas.
df2=df.ix[:,['A','B','C']]
#print("first df2 head :",df2.head())

list1=[]
list2=[]

for i in range(len(df['A'])):

    valoneless=(df['A'][i])-1

    valtwoless=(df['A'][i]-2)

    if (any(df['A']==valoneless)):

        if (df['B'][i])==df['C'][i]:
                val1='yes'
                list1.append(val1)

        else :
            val1='No'
            list1.append(val1)

    else:
        val1 = 'nan'
        list1.append(val1)

    if (any(df['A'] == valtwoless)):

            if (df['B'][i]) == df['C'][i]:
                val2 = 'yes'
                list2.append(val2)

            else:
                val2 = 'No'
                list2.append(val2)

    else:
            val2 = 'nan'
            list2.append(val2)

df2['A-1']=list1
df2['A-2']=list2


print(df2.head())

df2.to_csv("firstcolumn.txt",index=False,sep=" ",na_rep='nan')

【讨论】:

  • 感谢您的回复,我会检查您的解决方案并让您知道它是否按预期工作
  • 我还有另一列是客户名称,此代码必须适用于每个客户。上面的示例适用于一个客户。如果我包含列客户名称,代码是否有效??
猜你喜欢
  • 2020-09-26
  • 1970-01-01
  • 2015-11-30
  • 2021-07-12
  • 2023-02-05
  • 2017-09-17
  • 1970-01-01
  • 2021-11-22
  • 2018-08-15
相关资源
最近更新 更多