按照列中子字符串排序的Pandas数据框。

9

给定一个DataFrame:

    name             email
0   Carl    carl@yahoo.com
1    Bob     bob@gmail.com
2  Alice   alice@yahoo.com
3  David  dave@hotmail.com
4    Eve     eve@gmail.com

如何按电子邮件的域名(按字母顺序,升序)和“@”符号之前的字符串对其进行排序?

上述排序后的结果应为:

    name             email
0    Bob     bob@gmail.com
1    Eve     eve@gmail.com
2  David  dave@hotmail.com
3  Alice   alice@yahoo.com
4   Carl    carl@yahoo.com
2个回答

7

使用:

df = df.reset_index(drop=True)
idx = df['email'].str.split('@', expand=True).sort_values([1,0]).index
df = df.reindex(idx).reset_index(drop=True)
print (df)
    name             email
0    Bob     bob@gmail.com
1    Eve     eve@gmail.com
2  David  dave@hotmail.com
3  Alice   alice@yahoo.com
4   Carl    carl@yahoo.com

说明:

  1. 使用drop=True对默认唯一索引进行首次reset_index
  2. 然后将值split到新的DataFrame并进行sort_values
  3. 最后按照新顺序reindex到新的顺序

1
太棒了!真的很棒!这是一个非常好的答案。 - edesz

3

选项 1
sorted + reindex

df = df.set_index('email')
df.reindex(sorted(df.index, key=lambda x: x.split('@')[::-1])).reset_index()

              email   name
0     bob@gmail.com    Bob
1     eve@gmail.com    Eve
2  dave@hotmail.com  David
3   alice@yahoo.com  Alice
4    carl@yahoo.com   Carl

选项2
sorted + pd.DataFrame
作为另一种选择,您可以通过重新创建一个新的DataFrame来放弃选项1中的reindex调用。

pd.DataFrame(
    sorted(df.values, key=lambda x: x[1].split('@')[::-1]), 
    columns=df.columns
)

    name             email
0    Bob     bob@gmail.com
1    Eve     eve@gmail.com
2  David  dave@hotmail.com
3  Alice   alice@yahoo.com
4   Carl    carl@yahoo.com

可以用列名代替x[1]来实现Option 2吗?我尝试了x["email"],但是出现了错误。 - IamTheWalrus
@IamTheWalrus 不,这是不可能的。sorted 操作的是 df.values,而这些只能用整数索引。 - cs95
@COLDSPEED 谢谢。我用 df.columns.get_loc("email") 成功获取了列索引,并将其与您的解决方案结合使用。我更喜欢这种方法,因为我的实际数据框从 csv 中读取了许多列,并且有时我会更改其中包含的列以及顺序。 - IamTheWalrus
@IamTheWalrus 非常有创意!谢谢。 - cs95

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接