Pandas Groupby : 문자열 통합을 얻는 방법


122

다음과 같은 데이터 프레임이 있습니다.

   A         B       C
0  1  0.749065    This
1  2  0.301084      is
2  3  0.463468       a
3  4  0.643961  random
4  1  0.866521  string
5  2  0.120737       !

부름

In [10]: print df.groupby("A")["B"].sum()

돌아올 것이다

A
1    1.615586
2    0.421821
3    0.463468
4    0.643961

이제 "C"열에 대해 "동일"을 수행하고 싶습니다. 해당 열에 문자열이 포함되어 있기 때문에 sum ()은 작동하지 않습니다 (문자열을 연결한다고 생각할 수 있지만). 내가 정말로보고 싶은 것은 각 그룹에 대한 목록 또는 문자열 세트입니다.

A
1    {This, string}
2    {is, !}
3    {a}
4    {random}

나는 이것을 할 방법을 찾으려고 노력하고 있습니다.

Series.unique () ( http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.unique.html )는 작동하지 않지만

df.groupby("A")["B"]

이다

pandas.core.groupby.SeriesGroupBy object

그래서 어떤 시리즈 방법이 작동하길 바랬습니다. 어떤 아이디어?

답변:


178
In [4]: df = read_csv(StringIO(data),sep='\s+')

In [5]: df
Out[5]: 
   A         B       C
0  1  0.749065    This
1  2  0.301084      is
2  3  0.463468       a
3  4  0.643961  random
4  1  0.866521  string
5  2  0.120737       !

In [6]: df.dtypes
Out[6]: 
A      int64
B    float64
C     object
dtype: object

자체 함수를 적용 할 때 숫자가 아닌 열을 자동으로 제외하지 않습니다. 그러나 이것은의 응용 프로그램보다 느립니다 .sum().groupby

In [8]: df.groupby('A').apply(lambda x: x.sum())
Out[8]: 
   A         B           C
A                         
1  2  1.615586  Thisstring
2  4  0.421821         is!
3  3  0.463468           a
4  4  0.643961      random

sum 기본적으로 연결

In [9]: df.groupby('A')['C'].apply(lambda x: x.sum())
Out[9]: 
A
1    Thisstring
2           is!
3             a
4        random
dtype: object

원하는 것을 거의 할 수 있습니다.

In [11]: df.groupby('A')['C'].apply(lambda x: "{%s}" % ', '.join(x))
Out[11]: 
A
1    {This, string}
2           {is, !}
3               {a}
4          {random}
dtype: object

한 번에 한 그룹 씩 전체 프레임에서이 작업을 수행합니다. 열쇠는Series

def f(x):
     return Series(dict(A = x['A'].sum(), 
                        B = x['B'].sum(), 
                        C = "{%s}" % ', '.join(x['C'])))

In [14]: df.groupby('A').apply(f)
Out[14]: 
   A         B               C
A                             
1  2  1.615586  {This, string}
2  4  0.421821         {is, !}
3  3  0.463468             {a}
4  4  0.643961        {random}

이제 이러한 작업이 벡터화되어 applylambdas 의 필요성이 제거 된 것 같습니다 . 나는 왜 pandas실제로 합산 문자열에 오류를 반환하지 않는지 궁금해했습니다 .
NelsonGon

1
문자열을 연결하고 그 사이에 문자를 추가하려는 경우 아래 @voithos에서 권장하는 .agg 솔루션이 여기에서 권장하는 .apply보다 훨씬 빠릅니다. 내 테스트에서 나는 5-10 배 더 빨라졌습니다.
Doubledown

70

apply방법을 사용 하여 그룹화 된 데이터에 임의의 함수를 적용 할 수 있습니다 . 따라서 세트를 원하면 set. 목록을 원하시면 신청하십시오 list.

>>> d
   A       B
0  1    This
1  2      is
2  3       a
3  4  random
4  1  string
5  2       !
>>> d.groupby('A')['B'].apply(list)
A
1    [This, string]
2           [is, !]
3               [a]
4          [random]
dtype: object

다른 것을 원한다면 원하는 것을 수행하는 함수를 작성하십시오 apply.


잘 작동하지만 A 열이 없습니다.
Vineesh TP 2010 년

@VineeshTP : 열 A가 그룹화 열로 사용되었으므로 예제에서 볼 수 있듯이 인덱스에 있습니다. 을 사용하여 열로 다시 가져올 수 있습니다 .reset_index().
BrenBarn

30

당신은 사용할 수 있습니다 aggregate(또는 agg값을 연결하는) 기능. (테스트되지 않은 코드)

df.groupby('A')['B'].agg(lambda col: ''.join(col))

실제로 작동한다. 놀랄 만한. @voithos가 "unested"라고 언급했듯이, 저는 그다지 낙관적이지 않았습니다. 비트 나는 그의 버전을 agg 사전의 항목으로 테스트했으며 의도 한대로 작동했습니다. .agg ({ 'tp': 'sum', 'BaseWgt': 'max', 'TP_short': lambda col : ','.join (col)}) Made my day
matthhias

2
특정 유형의 구분 기호와 함께 문자열을 연결하려는 경우이 .agg 제안이 .apply보다 훨씬 빠르다는 것을 알았습니다. 600k + 텍스트 문자열 데이터 세트의 경우 동일한 결과를 5-10 배 더 빠르게 얻었습니다.
Doubledown

14

이것을 시도해 볼 수 있습니다.

df.groupby('A').agg({'B':'sum','C':'-'.join})

2
검토에서 : 답변에 더 많은 설명을 추가해 주시겠습니까?
toti08

1
Groupby는 'A'열에 적용되고 agg 함수를 사용하면 다른 열에서 다른 함수를 사용하여 'C'열의 요소를 합산하고 'C'열의 요소를 연결하면서 단어 사이에 '-'를 삽입 할 수 있습니다
user3241146

8

간단한 해결책은 다음과 같습니다.

>>> df.groupby(['A','B']).c.unique().reset_index()

이것이 정답이어야합니다. 깔끔하게 대답합니다. 감사합니다!
imsrgadich

경우에 누군가가 문자열로 목록의 내용에 합류에 관심이있는 경우 df.groupby(['A','B']).c.unique().apply(lambda x: ';'.join(x)).reset_index()
비벡 - Ananth

8

명명 된 집계 pandas >= 0.25.0

pandas 버전 0.25.0부터는 그룹화, 집계 및 동시에 열에 새 이름을 할당 할 수있는 집계 이름이 지정되었습니다. 이렇게하면 MultiIndex 열을 가져올 수 없으며 포함 된 데이터를 고려할 때 열 이름이 더 의미가 있습니다.


집계 및 문자열 목록 가져 오기

grp = df.groupby('A').agg(B_sum=('B','sum'),
                          C=('C', list)).reset_index()

print(grp)
   A     B_sum               C
0  1  1.615586  [This, string]
1  2  0.421821         [is, !]
2  3  0.463468             [a]
3  4  0.643961        [random]

문자열 집계 및 결합

grp = df.groupby('A').agg(B_sum=('B','sum'),
                          C=('C', ', '.join)).reset_index()

print(grp)
   A     B_sum             C
0  1  1.615586  This, string
1  2  0.421821         is, !
2  3  0.463468             a
3  4  0.643961        random

6

데이터 프레임에서 B 열을 덮어 쓰려면 다음과 같이하면됩니다.

    df = df.groupby('A',as_index=False).agg(lambda x:'\n'.join(x))

2

@Erfan의 좋은 대답에 따라 집계 값 분석에서 대부분의 경우 이러한 기존 문자 값의 고유 한 가능한 조합을 원합니다.

unique_chars = lambda x: ', '.join(x.unique())
(df
 .groupby(['A'])
 .agg({'C': unique_chars}))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.