Python 熊猫群比:如何获得字符串的并集
我有这样一个数据帧:Python 熊猫群比:如何获得字符串的并集,python,pandas,Python,Pandas,我有这样一个数据帧: 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.421
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()不起作用
df.groupby("A")["B"]
是一个
所以我希望任何级数方法都能奏效。有什么想法吗
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()
应用于分组比
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
一次一组,在整个框架上进行此操作。关键是返回一个系列
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
如果您还需要其他功能,只需编写一个函数来实现您想要的功能,然后应用该功能。您可以使用
聚合
(或agg
)函数来连接这些值。(未测试代码)
一个简单的解决办法是:
>>> 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的命名聚合
自从pandas版本0.25.0以来,我们已经命名了聚合,我们可以在其中进行分组、聚合,同时为列指定新名称。这样,我们就不会得到多索引列,而且考虑到它们包含的数据,列名更有意义:
聚合并获取字符串列表
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
聚合并连接字符串
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}))
它确实有效。太神了正如@voithos提到的“未经测试”,我并不十分乐观。我把他的版本作为agg字典中的一个条目进行了测试,它按预期工作:.agg({'tp':'sum','BaseWgt':'max','tp_short':lambda col:','.join(col)})是我的一天。如果您试图用某种类型的分隔符将字符串合并在一起,我发现这个.agg建议比.apply快得多。对于一个600k+文本字符串的数据集,我得到的相同结果快了5-10倍。这应该是正确的答案。让你清楚地回答。谢谢!如果某人有兴趣将列表内容加入字符串df.groupby(['a','B']).c.unique().apply(lambda x:';').join(x)).reset_index()
From review:您能为您的答案添加更多解释吗?Groupby应用于“A”列,使用agg函数,我可以在不同的列上使用不同的函数,比如对“C”列中的元素求和,将列“C”中的元素串联起来,同时在字之间插入“-”,这些操作现在似乎已矢量化,不再需要apply
和lambda
s。我来这里想知道为什么pandas
实际上是concats而不是返回一个求和字符串的错误。如果您试图在字符串之间加上一个字符,下面@voithos推荐的.agg解决方案要比这里推荐的.apply快得多。在我的测试中,我的速度提高了5-10倍。工作正常,但缺少列A。@VineeshTP:列A被用作分组列,因此它在索引中,如示例中所示。您可以使用.reset\u index()
将其作为列返回。为了确认我的理解,lambda中使用的.unique()
正在确定包含所有唯一值的序列是否在指定的group by values中?如果是,pandas是否将每个唯一值(按值分组)临时存储在unique\u chars
变量之外的某个位置,以确定在最终将值分配给变量之前哪些值实际上是唯一的?也许值得一个新的SO问题。@deesolieunique_chars
是向量x的函数。Lambda是在python中创建单行函数的简称。然后将该函数与每个列向量一起用作输入。我理解lambda函数。假设我们有df.groupby(['A'])['B'].transform(lambda x:','.join(x.unique())
,我很好奇pandas是如何临时存储group by序列中的每个值,以检查正在进行的值是否已经在连接的字符串中。同样,这可能是一个更大的问题,因此应作为一个新的SO问题进行提问。@deesolie No pandas不检查该值是否已在连接的字符串中。你点错菜了。这是一个矢量化操作。首先,unique返回唯一字符的向量。其次,.join
将向量的所有元素连接在一起。谢谢Paul,用这种方式查看操作顺序更容易理解这一行是如何工作的。