PANDS의 SQL-like window 함수: Python Pandas Dataframe의 Row Numbering
저는 sql 배경 출신이고 다음 데이터 처리 단계를 자주 사용합니다.
- 데이터 테이블을 하나 이상의 필드로 분할
- 각 파티션에 대해 행을 하나 이상의 다른 필드로 순위를 매기는 각 행에 행 번호를 추가합니다. 여기서 분석가는 오름차순 또는 내림차순을 지정합니다.
EX:
df = pd.DataFrame({'key1' : ['a','a','a','b','a'],
'data1' : [1,2,2,3,3],
'data2' : [1,10,2,3,30]})
df
data1 data2 key1
0 1 1 a
1 2 10 a
2 2 2 a
3 3 3 b
4 3 30 a
이 sql window 기능과 동등한 PANDS를 수행하는 방법을 찾고 있습니다.
RN = ROW_NUMBER() OVER (PARTITION BY Key1 ORDER BY Data1 ASC, Data2 DESC)
data1 data2 key1 RN
0 1 1 a 1
1 2 10 a 2
2 2 2 a 3
3 3 3 b 1
4 3 30 a 4
저는 '파티션'이 없는 곳에서 일하게 된 다음과 같은 것을 시도해 보았습니다.
def row_number(frame,orderby_columns, orderby_direction,name):
frame.sort_index(by = orderby_columns, ascending = orderby_direction, inplace = True)
frame[name] = list(xrange(len(frame.index)))
저는 이 아이디어를 파티션(판다의 그룹)과 함께 사용하도록 확장하려고 했지만 다음과 같은 방법이 적용되지 않았습니다.
df1 = df.groupby('key1').apply(lambda t: t.sort_index(by=['data1', 'data2'], ascending=[True, False], inplace = True)).reset_index()
def nf(x):
x['rn'] = list(xrange(len(x.index)))
df1['rn1'] = df1.groupby('key1').apply(nf)
근데 이거 할 때 NaN이 많이 나왔어요.
이상적으로 sql의 윈도우 기능 기능을 복제할 수 있는 간단한 방법이 있습니다(윈도우 기반 Aggregate를 파악했습니다...)팬더에서는 하나의 라이너(liner)입니다. 누군가가 팬더에서 이와 같은 줄을 타는 가장 관용적인 방법을 저와 공유할 수 있을까요?
사용할 수도 있습니다.sort_values()
,groupby()
그리고 마침내cumcount() + 1
:
df['RN'] = df.sort_values(['data1','data2'], ascending=[True,False]) \
.groupby(['key1']) \
.cumcount() + 1
print(df)
산출량:
data1 data2 key1 RN
0 1 1 a 1
1 2 10 a 2
2 2 2 a 3
3 3 3 b 1
4 3 30 a 4
팬더 0.18로 PS 테스트
group by.rank 함수를 사용합니다.여기 작동 예시가 있습니다.
df = pd.DataFrame({'C1':['a', 'a', 'a', 'b', 'b'], 'C2': [1, 2, 3, 4, 5]})
df
C1 C2
a 1
a 2
a 3
b 4
b 5
df["RANK"] = df.groupby("C1")["C2"].rank(method="first", ascending=True)
df
C1 C2 RANK
a 1 1
a 2 2
a 3 3
b 4 1
b 5 2
를 사용하면 됩니다.groupby
에 맞추어 두 번rank
방법:
In [11]: g = df.groupby('key1')
min method 인수를 사용하여 동일한 데이터1을 공유하는 값에 동일한 RN을 부여합니다.
In [12]: g['data1'].rank(method='min')
Out[12]:
0 1
1 2
2 2
3 1
4 4
dtype: float64
In [13]: df['RN'] = g['data1'].rank(method='min')
그런 다음 이 결과를 기준으로 그룹화하고 데이터2에 대한 순위를 추가합니다.
In [14]: g1 = df.groupby(['key1', 'RN'])
In [15]: g1['data2'].rank(ascending=False) - 1
Out[15]:
0 0
1 0
2 1
3 0
4 0
dtype: float64
In [16]: df['RN'] += g1['data2'].rank(ascending=False) - 1
In [17]: df
Out[17]:
data1 data2 key1 RN
0 1 1 a 1
1 2 10 a 2
2 2 2 a 3
3 3 3 b 1
4 3 30 a 4
이것을 할 수 있는 고유한 방법이 있어야 할 것 같습니다(있을지도 모릅니다!).
사용가능transform
그리고.Rank
여기에 한가지 예시가 있습니다.
df = pd.DataFrame({'C1' : ['a','a','a','b','b'],
'C2' : [1,2,3,4,5]})
df['Rank'] = df.groupby(by=['C1'])['C2'].transform(lambda x: x.rank())
df
자세한 내용은 팬더 랭크 방법을 살펴보세요.
pandas.lib.fast_zip()
배열 목록에서 튜플 배열을 만들 수 있습니다.이 함수를 사용하여 튜플 시리즈를 만든 다음 순위를 매길 수 있습니다.
values = {'key1' : ['a','a','a','b','a','b'],
'data1' : [1,2,2,3,3,3],
'data2' : [1,10,2,3,30,20]}
df = pd.DataFrame(values, index=list("abcdef"))
def rank_multi_columns(df, cols, **kw):
data = []
for col in cols:
if col.startswith("-"):
flag = -1
col = col[1:]
else:
flag = 1
data.append(flag*df[col])
values = pd.lib.fast_zip(data)
s = pd.Series(values, index=df.index)
return s.rank(**kw)
rank = df.groupby("key1").apply(lambda df:rank_multi_columns(df, ["data1", "-data2"]))
print rank
결과:
a 1
b 2
c 3
d 2
e 4
f 1
dtype: float64
언급URL : https://stackoverflow.com/questions/17775935/sql-like-window-functions-in-pandas-row-numbering-in-python-pandas-dataframe
'programing' 카테고리의 다른 글
MariaDB: 저장 프로시저 잠금 행에서 SELECT (0) | 2023.10.20 |
---|---|
스크립트를 사용하여 이미지 캐시하기 (0) | 2023.10.20 |
XPath: 자식 노드에서 부모 노드 가져오기 (0) | 2023.10.20 |
pt로 할까요, px로 할까요? (0) | 2023.10.20 |
팝업에서 우커머스 체크아웃 (0) | 2023.10.20 |