code

판다의 사용자 지정 목록에 따라 정렬

starcafe 2023. 8. 6. 10:14
반응형

판다의 사용자 지정 목록에 따라 정렬

읽은 후: http://pandas.pydata.org/pandas-docs/version/0.13.1/generated/pandas.DataFrame.sort.html

사용자 정의 목록으로 열을 정렬하는 방법을 아직도 알 수 없는 것 같습니다.기본 정렬은 알파벳 순입니다.예를 들어보겠습니다.다음은 제(매우 요약된) 데이터 프레임입니다.

             Player      Year   Age   Tm     G
2967     Cedric Hunter   1991    27  CHH     6
5335     Maurice Baker   2004    25  VAN     7
13950    Ratko Varda     2001    22  TOT     60
6141     Ryan Bowen      2009    34  OKC     52
6169     Adrian Caldwell 1997    31  DAL     81

플레이어, 연도, Tm 순으로 정렬할 수 있기를 원합니다.플레이어 및 연도별 기본 정렬은 정상 순서로 가능합니다.하지만 팀이 알파벳 순으로 정렬되는 것을 원하지 않습니다. 항상 상위에 있는 TOT를 원합니다.

다음은 내가 작성한 목록입니다.

sorter = ['TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL', 'DEN',
   'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL',
   'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI',
   'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN',
   'WAS', 'WSB']

위의 링크를 통해 읽은 후, 저는 이것이 효과가 있을 것이라고 생각했지만 효과가 없었습니다.

df.sort(['Player', 'Year', 'Tm'], ascending = [True, True, sorter])

ATL이 여전히 맨 위에 있습니다. 즉, 사용자 지정 목록에 따라 정렬되지 않고 알파벳 순으로 정렬되었습니다.어떤 도움이라도 주시면 정말 감사하겠습니다, 도저히 이해할 수가 없습니다.

아래 답변은 오래된 답변입니다.여전히 작동한다.어쨌든, 다른 매우 우아한 해결책이 아래에 게시되었습니다.key논쟁.


저는 판다 15.1로 범주형 시리즈를 사용할 수 있다는 것을 방금 발견했습니다(https://pandas.pydata.org/docs/user_guide/categorical.html) .

예를 들어, 동일한 데이터 프레임과 정렬기를 정의합니다.

import pandas as pd

data = {
    'id': [2967, 5335, 13950, 6141, 6169],
    'Player': ['Cedric Hunter', 'Maurice Baker', 
               'Ratko Varda' ,'Ryan Bowen' ,'Adrian Caldwell'],
    'Year': [1991, 2004, 2001, 2009, 1997],
    'Age': [27, 25, 22, 34, 31],
    'Tm': ['CHH', 'VAN', 'TOT', 'OKC', 'DAL'],
    'G': [6, 7, 60, 52, 81]
}

# Create DataFrame
df = pd.DataFrame(data)

# Define the sorter
sorter = ['TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL', 'DEN',
          'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL',
          'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI',
          'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN', 'WAS', 'WSB']

범주 순서인 데이터 프레임과 정렬기를 사용하면 판다 15.1에서 다음을 수행할 수 있습니다.

# Convert Tm-column to category and in set the sorter as categories hierarchy
# You could also do both lines in one just appending the cat.set_categories()
df.Tm = df.Tm.astype("category")
df.Tm = df.Tm.cat.set_categories(sorter)

print(df.Tm)
Out[48]: 
0    CHH
1    VAN
2    TOT
3    OKC
4    DAL
Name: Tm, dtype: category
Categories (38, object): [TOT < ATL < BOS < BRK ... UTA < VAN < WAS < WSB]

df.sort_values(["Tm"])  ## 'sort' changed to 'sort_values'
Out[49]: 
   Age   G           Player   Tm  Year     id
2   22  60      Ratko Varda  TOT  2001  13950
0   27   6    Cedric Hunter  CHH  1991   2967
4   31  81  Adrian Caldwell  DAL  1997   6169
3   34  52       Ryan Bowen  OKC  2009   6141
1   25   7    Maurice Baker  VAN  2004   5335

다음은 데이터 프레임에서 사전 정렬을 수행하는 예제입니다.이 아이디어는 특정 정렬을 기반으로 숫자 인덱스를 만드는 것입니다.그런 다음 인덱스를 기준으로 숫자 정렬을 수행합니다.열이 데이터 프레임에 추가된 다음 제거됩니다.

import pandas as pd

# Create DataFrame
df = pd.DataFrame(
{'id':[2967, 5335, 13950, 6141, 6169],
    'Player': ['Cedric Hunter', 'Maurice Baker',
               'Ratko Varda' ,'Ryan Bowen' ,'Adrian Caldwell'],
    'Year': [1991, 2004, 2001, 2009, 1997],
    'Age': [27, 25, 22, 34, 31],
    'Tm': ['CHH' ,'VAN' ,'TOT' ,'OKC', 'DAL'],
    'G': [6, 7, 60, 52, 81]})

# Define the sorter
sorter = ['TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL','DEN',
          'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL',
          'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI',
          'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN',
          'WAS', 'WSB']

# Create the dictionary that defines the order for sorting
sorterIndex = dict(zip(sorter, range(len(sorter))))

# Generate a rank column that will be used to sort
# the dataframe numerically
df['Tm_Rank'] = df['Tm'].map(sorterIndex)

# Here is the result asked with the lexicographic sort
# Result may be hard to analyze, so a second sorting is
# proposed next
## NOTE: 
## Newer versions of pandas use 'sort_values' instead of 'sort'
df.sort_values(['Player', 'Year', 'Tm_Rank'],
        ascending = [True, True, True], inplace = True)
df.drop('Tm_Rank', 1, inplace = True)
print(df)

# Here is an example where 'Tm' is sorted first, that will 
# give the first row of the DataFrame df to contain TOT as 'Tm'
df['Tm_Rank'] = df['Tm'].map(sorterIndex)
## NOTE: 
## Newer versions of pandas use 'sort_values' instead of 'sort'
df.sort_values(['Tm_Rank', 'Player', 'Year'],
        ascending = [True , True, True], inplace = True)
df.drop('Tm_Rank', 1, inplace = True)
print(df)
df1 = df.set_index('Tm')
df1.loc[sorter]

@kstajer가 언급했듯이 팬더 1.0.0 이후에는 대신 재인덱스를 사용합니다.

df1.reindex(sorter)

버전 1.1.0 이후에는key정렬 값 속성:

df.sort_values(by="Tm", key=lambda column: column.map(lambda e: sorter.index(e)), inplace=True)

판다 1.1.0 문서에 따르면, 다음과 같이 분류하는 것이 가능해졌습니다.key와 같은 매개 변수sorted함수를 지정합니다.정렬 방법은 다음과 같습니다.Tm

import pandas as pd


data = {
    'id': [2967, 5335, 13950, 6141, 6169],
    'Player': ['Cedric Hunter', 'Maurice Baker', 
               'Ratko Varda' ,'Ryan Bowen' ,'Adrian Caldwell'],
    'Year': [1991, 2004, 2001, 2009, 1997],
    'Age': [27, 25, 22, 34, 31],
    'Tm': ['CHH', 'VAN', 'TOT', 'OKC', 'DAL'],
    'G': [6, 7, 60, 52, 81]
}

# Create DataFrame
df = pd.DataFrame(data)


def tm_sorter(column):
    """Sort function"""
    teams = ['TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL', 'DEN',
       'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL',
       'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI',
       'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN',
       'WAS', 'WSB']
    correspondence = {team: order for order, team in enumerate(teams)}
    return column.map(correspondence)

df.sort_values(by='Tm', key=tm_sorter)

안타깝게도 이 기능은 1열로 정렬할 때만 사용할 수 있는 것 같습니다.keys는 허용되지 않습니다).에 의해 회피될 수 있습니다.groupby

df.sort_values(['Player', 'Year']) \
  .groupby(['Player', 'Year']) \
  .apply(lambda x: x.sort_values(by='Tm', key=tm_sorter)) \
  .reset_index(drop=True)

사용 방법을 알고 있는 경우keysort_values여러 개의 열을 사용하여 알려 주십시오.

이것은 단지 몇 줄로 일을 합니다.

# Create a dummy df with the required list and the col name to sort on
dummy = pd.Series(sort_list, name = col_name).to_frame()

# Use left merge on the dummy to return a sorted df
sorted_df = pd.merge(dummy, df, on = col_name, how = 'left')

한 후 인스설정DataFrame.loc단일 사용자 지정 목록으로 주문해야 할 경우 유용합니다. ㅠㅠloc를 생성합니다.NaN 행의 값 행sorter데이터 프레임에 없는 데이터는 먼저 교차점을 찾을 것입니다.이렇게 하면 원하지 않는 업캐스팅을 방지할 수 있습니다.목록에 없는 값을 가진 행은 모두 제거됩니다.

true_sort = [s for s in sorter if s in df.Tm.unique()]
df = df.set_index('Tm').loc[true_sort].reset_index()

    Tm     id           Player  Year  Age   G
0  TOT  13950      Ratko Varda  2001   22  60
1  CHH   2967    Cedric Hunter  1991   27   6
2  DAL   6169  Adrian Caldwell  1997   31  81
3  OKC   6141       Ryan Bowen  2009   34  52
4  VAN   5335    Maurice Baker  2004   25   7

시작 데이터:

print(df)
      id           Player  Year  Age   Tm   G
0   2967    Cedric Hunter  1991   27  CHH   6
1   5335    Maurice Baker  2004   25  VAN   7
2  13950      Ratko Varda  2001   22  TOT  60
3   6141       Ryan Bowen  2009   34  OKC  52
4   6169  Adrian Caldwell  1997   31  DAL  81

sorter = ['TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL', 'DEN',
          'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL',
          'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI',
          'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN', 'WAS', 'WSB']

범주형 열별 정렬에만 관심이 있는 사용자를 위한 부분 솔루션:

사용자 정의 목록에서 정렬 순서 매퍼를 만드는 도우미 기능을 사용하여 이 작업을 수행할 수 있습니다.

이 예제에는 한 열의 값만 포함되지만 모든 열에 발생하는 값을 포함하는 사용자 지정 순서 목록을 만들어 다른 열을 포함하도록 확장할 수 있습니다.당연히 정렬 필드에 가능한 모든 값을 사용하여 사용자 정의 목록을 구성해야 하므로, 이는 대부분 범주형 정렬에 유용하며 연속형 변수(가능한 값이 미리 알려져 있지 않은 경우)와 카디널리티가 매우 높은 열에는 적합하지 않습니다.

import pandas as pd

# set up a dummy dataframe
df = pd.DataFrame({'a':list('abcde'), 'b':range(5)})

# helper function
def make_sorter(l):
    """
    Create a dict from the list to map to 0..len(l)
    Returns a mapper to map a series to this custom sort order
    """
    sort_order = {k:v for k,v in zip(l, range(len(l)))}
    return lambda s: s.map(lambda x: sort_order[x])

# define a custom sort order
my_order = list('bdeca')

df.sort_values('a', key=make_sorter(my_order))

   a b
1  b 1
3  d 3
4  e 4
2  c 2
0  a 0

OP의 데이터 사용:

df = pd.DataFrame({
    'id':[2967, 5335, 13950, 6141, 6169],
    'Player': ['Cedric Hunter', 'Maurice Baker',
               'Ratko Varda' ,'Ryan Bowen' ,'Adrian Caldwell'],
    'Year': [1991, 2004, 2001, 2009, 1997],
    'Age': [27, 25, 22, 34, 31],
    'Tm': ['CHH' ,'VAN' ,'TOT' ,'OKC', 'DAL'],
    'G': [6, 7, 60, 52, 81]
})

# Define the sorter
sorter = [
    'TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL',
    'DEN', 'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA',
    'MIL', 'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL',
    'PHI', 'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN',
    'WAS', 'WSB'
]

df.sort_values('Tm', key=make_sorter(sorter))

      id           Player  Year  Age   Tm   G
2  13950      Ratko Varda  2001   22  TOT  60
0   2967    Cedric Hunter  1991   27  CHH   6
4   6169  Adrian Caldwell  1997   31  DAL  81
3   6141       Ryan Bowen  2009   34  OKC  52
1   5335    Maurice Baker  2004   25  VAN   7

제 아이디어는 인덱스별로 정렬 번호를 생성한 다음 정렬 번호를 원래 데이터 프레임에 병합하는 것입니다.

import pandas as pd

df = pd.DataFrame(
{'id':[2967, 5335, 13950, 6141, 6169],\
 'Player': ['Cedric Hunter', 'Maurice Baker' ,\
            'Ratko Varda' ,'Ryan Bowen' ,'Adrian Caldwell'],\
 'Year': [1991 ,2004 ,2001 ,2009 ,1997],\
 'Age': [27 ,25 ,22 ,34 ,31],\
 'Tm':['CHH' ,'VAN' ,'TOT' ,'OKC' ,'DAL'],\
 'G':[6 ,7 ,60 ,52 ,81]})

sorter = ['TOT', 'ATL', 'BOS', 'BRK', 'CHA', 'CHH', 'CHI', 'CLE', 'DAL', 'DEN',
   'DET', 'GSW', 'HOU', 'IND', 'LAC', 'LAL', 'MEM', 'MIA', 'MIL',
   'MIN', 'NJN', 'NOH', 'NOK', 'NOP', 'NYK', 'OKC', 'ORL', 'PHI',
   'PHO', 'POR', 'SAC', 'SAS', 'SEA', 'TOR', 'UTA', 'VAN',
   'WAS', 'WSB']

x = pd.DataFrame({'Tm': sorter})
x.index = x.index.set_names('number')
x = x.reset_index()

df = pd.merge(df, x, how='left', on='Tm')

df.sort_values(['Player', 'Year', 'number'], \
        ascending = [True, True, True], inplace = True)
df.drop('number', 1, inplace = True)

언급URL : https://stackoverflow.com/questions/23482668/sorting-by-a-custom-list-in-pandas

반응형