【问题标题】:Link dataframe columns on another dataframe, under condition在条件下链接另一个数据帧上的数据帧列
【发布时间】:2021-07-17 09:16:11
【问题描述】:

以下问题: Python Pandas Only Compare Identically Labeled DataFrame Objects & How to create a new data frame based on conditions from another data frame.

我正在尝试在已经存在的数据框 df1 中创建一个列,其值以另一个具有不同索引和列的现有数据框 df2 为条件。

在 df2 ['Home'] 城市有一个 ['Home_ranking']。我需要将 df1 中的 ['Home_ranking'] 与 df2 匹配,条件是 ['Home'] 城市应该匹配。 比如B市是df1中的第一个['Home']城市,我需要得到它在df2中的排名,即2。所以df1中的第一个['Home_ranking']是2,以此类推。

df1 有 50 行和更多列,而 df2 只有 20 行和 4 列。

>>> print(df1)
      Home     Away     Home_ranking    Away_ranking    [other columns..]
0   city B   city C                0               0
1   city D   city D                0               0
2   city B   city D                0               0
3   city A   city A                0               0

>>> print(df2)
      Home     Away     Home_ranking    Away_ranking
0   city A   city B               12               5
1   city D   city C                4               7
2   city F   city A                1               9
3   city B   city D                2               8

预期结果

>>> print(df1)
      Home     Away     Home_ranking    Away_ranking
0   city B   city C                2               7
1   city D   city D                4               8
2   city B   city D                2               8
3   city A   city A               12               9

我已经尝试了前面问题中建议的许多事情,但似乎没有一个对我有用。我也试过:

for i in df1.Home :
    if df1.Home == df2.Home :
       df1['Home_ranking'][i] = df2.Home_ranking[i]

产生“ValueError:只能比较标签相同的系列对象”

df1['Home_ranking'][i] = df2.loc[(df2['Home'] == df1['Home'][i])].Home_ranking

yields "KeyError: 'city B' 我迷路了,欢迎任何帮助。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    你可以map()排名:

    • 对于Home_rankingsHome 列是匹配键,因此将df2 的索引设置为Home,并将其Home_ranking 映射到df1['Home']
    • 对于Away_rankings,键是Away,所以将df2的索引设置为Away并将其Away_ranking映射到df1['Away']
    df1['Home_ranking'] = df1['Home'].map(
        df2.drop_duplicates(subset=['Home']).set_index('Home')['Home_ranking'])
    
    df1['Away_ranking'] = df1['Away'].map(
        df2.drop_duplicates(subset=['Away']).set_index('Away')['Away_ranking'])
    
    #      Home    Away  Home_ranking  Away_ranking
    # 0  city B  city C             2             7
    # 1  city D  city D             4             8
    # 2  city B  city D             2             8
    # 3  city A  city A            12             9
    

    对于这个用例,映射应该比合并更快(并且规模更好):

    %%timeit
    df1['Home'].map(df2.drop_duplicates(subset=['Home']).set_index('Home')['Home_ranking'])
    df1['Away'].map(df2.drop_duplicates(subset=['Away']).set_index('Away')['Away_ranking'])
    
    # 2.92 ms ± 72.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    %%timeit
    (df1.drop(columns=['Home_ranking', 'Away_ranking'])
        .merge(df2[['Home', 'Home_ranking']], how='left', on='Home')
        .merge(df2[['Away', 'Away_ranking']], how='left', on='Away')
    
    # 4.59 ms ± 30.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    【讨论】:

    • 谢谢@tdy,我觉得这是朝着正确的方向发展,但它仍然会产生:'InvalidIndexError: Reindexing only valid with unique value Index objects'。我想我可能可以解决这个问题,但在代码行方面仍然很昂贵。这是否意味着 df1['Home'] 需要独特的价值? ..事实并非如此..
    • @JoeBadAss 啊好的,那么问题实际上是df2 中的骗子。更新后的答案(drop_duplicates)应该会解决这个问题。
    • 是的,谢谢@tdy!我被说服没有重复但有..
    【解决方案2】:

    您不需要循环。这是几个合并操作:

    import pandas
    
    df1 = pandas.DataFrame({
        "Home": list("BDBA"),
        "Away": list("CDDA"),
        "Home_Ranking": [0] * 4,
        "Away_Ranking": [0] * 4,
    })
    
    
    df2 = pandas.DataFrame({
        "Home": list("ADFB"),
        "Away": list("BCAD"),
        "Home_Ranking": [12, 4, 1 ,2],
        "Away_Ranking": [5, 7, 9, 8],
    })
    
    
    results = (
        df1.drop(columns=["Home_Ranking", "Away_Ranking"])
           .merge(df2[["Home", "Home_Ranking"]], how='left', on="Home")
           .merge(df2[["Away", "Away_Ranking"]], how='left', on="Away")
    )
    

    这让你:

    Home Away  Home_Ranking  Away_Ranking
       B    C             2             7
       D    D             4             8
       B    D             2             8
       A    A            12             9
    

    【讨论】:

    • 感谢@Paul H,它仅适用于一行,即与 df1 和 df2 中的 Home 和 Away 列匹配的行。不幸的是,其他不匹配的行得到了 nan
    • 如果键不匹配,你期望发生什么@JoeBadAss?
    • 感谢您的评论@Paul H。我的问题问得不好。我稍微改写了一下,希望它能回答你的问题。
    • @JoeBadAss 啊,我明白了。仍然不需要任何循环。检查更新
    猜你喜欢
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 2018-10-03
    • 2017-11-10
    • 1970-01-01
    相关资源
    最近更新 更多