如何得到字符串的联合

我有一个这样的数据框架:

   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}

我一直在想办法。

惟一()(http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.unique.html)不工作,但是

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

是一个

pandas.core.groupby.SeriesGroupBy object

所以我希望所有的系列方法都能奏效,有什么想法吗?

168003 次浏览
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}

可以使用 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

您可以使用 aggregate(或 agg)函数来连接这些值

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

一个简单的解决办法是:

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

你可以试试这个:

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

如果您想覆盖数据框架中的 B 列,这应该可以工作:

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

使用 pandas >= 0.25.0命名聚合

从熊猫版本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

根据@Erfan 的回答,大多数情况下,在分析聚合值时,你需要的是这些现有字符值的独特可能组合:

unique_chars = lambda x: ', '.join(x.unique())
(df
.groupby(['A'])
.agg({'C': unique_chars}))