【问题标题】:Select rows of pandas dataframe from list, in order of list从列表中选择熊猫数据框的行,按列表顺序
【发布时间】:2019-01-27 08:48:35
【问题描述】:

这个问题最初是作为评论提出的 here,但由于该问题被标记为重复,因此无法得到正确的答案。

对于给定的pandas.DataFrame,让我们说

df = DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3, 5]})
df

     A   B
0    5   1
1    6   2
2    3   3
3    4   5

我们如何根据列中的值从列表中选择行(例如'A'

例如

# from
list_of_values = [3,4,6]

# we would like, as a result
#      A   B
# 2    3   3
# 3    4   5
# 1    6   2

使用isin 提到的here 并不令人满意,因为它不能保持'A' 值的输入列表中的顺序。

如何实现上述目标?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    解决此问题的一种方法是将'A' 列设为index,并在新生成的pandas.DataFrame 上使用loc。最终,可以重置二次采样数据帧的索引。

    方法如下:

    ret = df.set_index('A').loc[list_of_values].reset_index(inplace=False)
    
    # ret is
    #      A   B
    # 0    3   3
    # 1    4   5
    # 2    6   2 
    

    注意,这种方法的缺点是原来的索引在这个过程中已经丢失了。

    更多关于pandas索引:What is the point of indexing in pandas?

    【讨论】:

    • 一个问题 - list_of_values 的所有值都在列中?可以list_of_values = [3,4,6,7,7,4] 吗?
    • 在实践中没有,但确实该解决方案存在不处理列外值的不便
    • 那么最好的是最通用的解决方案,不删除原始索引,使用重复值?
    【解决方案2】:

    merge 与由列表创建的助手DataFrame 和匹配列的列名一起使用:

    df = pd.DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3,5]})
    
    list_of_values = [3,6,4]
    df1 = pd.DataFrame({'A':list_of_values}).merge(df)
    print (df1)
       A  B
    0  3  3
    1  6  2
    2  4  5
    

    更通用的解决方案:

    df = pd.DataFrame({'A' : [5,6,5,3,4,4,6,5], 'B':range(8)})
    print (df)
       A  B
    0  5  0
    1  6  1
    2  5  2
    3  3  3
    4  4  4
    5  4  5
    6  6  6
    7  5  7
    
    list_of_values = [6,4,3,7,7,4]
    

    #create df from list 
    list_df = pd.DataFrame({'A':list_of_values})
    print (list_df)
       A
    0  6
    1  4
    2  3
    3  7
    4  7
    5  4
    
    #column for original index values
    df1 = df.reset_index()
    #helper column for count duplicates values
    df1['g'] = df1.groupby('A').cumcount()
    list_df['g'] = list_df.groupby('A').cumcount()
    
    #merge together, create index from column and remove g column
    df = list_df.merge(df1).set_index('index').rename_axis(None).drop('g', axis=1)
    print (df)
       A  B
    1  6  1
    4  4  4
    3  3  3
    5  4  5
    

    【讨论】:

    • 过程中原始索引丢失。
    • @Zero - 然后是必要的df1 = pd.DataFrame({'A':list_of_values}).merge(df.reset_index()).set_index('index').rename_axis(None)
    • 实际上,我发现这种方法在list_of_values包含重复值的情况下不起作用:不能保证保持顺序。对不起,我不得不取消投票作为答案
    • @syltruong - 我尝试为重复值 (4) 和不匹配值 (7) 创建更通用的解决方案。
    【解决方案3】:

    1]list_of_values 的通用方法。

    In [936]: dff = df[df.A.isin(list_of_values)]
    
    In [937]: dff.reindex(dff.A.map({x: i for i, x in enumerate(list_of_values)}).sort_values().index)
    Out[937]:
       A  B
    2  3  3
    3  4  5
    1  6  2
    

    2] 如果list_of_values 已排序。你可以使用

    In [926]: df[df.A.isin(list_of_values)].sort_values(by='A')
    Out[926]:
       A  B
    2  3  3
    3  4  5
    1  6  2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-31
      • 2020-11-20
      • 1970-01-01
      • 2017-08-09
      • 2018-03-30
      • 2015-10-19
      • 1970-01-01
      相关资源
      最近更新 更多