판다의 사용자 지정 목록에 따라 정렬
다 읽은 후: 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열로 정렬할 때만 사용할 수 있는 것 같습니다.key
s는 허용되지 않습니다).에 의해 회피될 수 있습니다.groupby
df.sort_values(['Player', 'Year']) \
.groupby(['Player', 'Year']) \
.apply(lambda x: x.sort_values(by='Tm', key=tm_sorter)) \
.reset_index(drop=True)
사용 방법을 알고 있는 경우key
에sort_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
'code' 카테고리의 다른 글
PowerShell 스크립트가 윈도우즈 스케줄링된 작업으로 실행되지 않음 (0) | 2023.08.06 |
---|---|
C의 intain() vs void main() (0) | 2023.08.06 |
Google Chrome용 Firebug와 유사한 디버거 (0) | 2023.08.06 |
PHP에서 register_globals는 무엇입니까? (0) | 2023.08.06 |
Python의 랜덤 해시 (0) | 2023.08.06 |