pandas explode 避免重复值
pandas explode avoid duplication of values
我在多列中有以下数据:
col1 col2 col3
123456 ['mary','ralph', ''bob'] ['bob','sam']
456789 ['george','fred', susie'] ['ralph','mary', 'bob']
789123 ['mary', bob'] ['bob']
我最终需要在每一列上添加一个 value_counts。为了将所有内容都从列表中删除,我正在尝试爆炸。我可以将值放入它们的列 post-explode,没问题。但是,那些了解 explode 的人都知道,我的 value_counts 会被膨胀,因为在将它应用到多个列时会重复 explode 导致的值
例如,分解产生这个:
col1 col2 col3
123456 mary bob
123456 mary sam
123456 mary george
123456 ralph bob
123456 ralph sam
123456 ralph george...etc.
显然,这会导致每列的准确 value_counts 是我需要的。
我尝试在每一列上循环爆炸,然后在每一列爆炸后匹配第一列和爆炸列并删除重复项,但不起作用。总是喜欢不成为房间里最聪明的人(更多需要学习)所以我把这个问题发给了你 pandas 充满想法的大师。 (看看我在那里做了什么?)。谢谢
我可以 value_counts 除了 col1 之外的所有列的预期输出是这样的:
123456 mary bob
123456 ralph sam
123456 bob george
456789 george ralph
456789 fred mary
456789 susie bob
789123 mary bob
789123 bob george
我们可以使用 stack
展开每个列表,然后使用 cumcount
创建代理索引
# if not real lists you'll need `literal_eval
from ast import literal_eval
s = df.set_index('col1').stack().map(literal_eval).explode().to_frame()
df1 = s.set_index(s.groupby(level=[0,1]).cumcount(),append=True).unstack(1).droplevel(0,1)
print(df1)
col2 col3
col1
123456 0 mary bob
1 ralph sam
2 bob george
456789 0 george ralph
1 fred mary
2 susie bob
789123 0 mary bob
1 bob george
IIUC 你可以 apply
而不是循环和分解:
print (df.set_index("col1").apply(pd.Series.explode))
col2 col3
col1
123456 mary bob
123456 ralph sam
123456 bob george
456789 george ralph
456789 fred mary
456789 susie bob
789123 mary bob
789123 bob george
对于不均匀列表:
s = df.set_index("col1").agg("sum").to_frame().explode(0)
print (s.groupby(level=0)[0].apply(pd.Series.value_counts))
col2 mary 2
bob 2
george 1
susie 1
ralph 1
john 1
fred 1
col3 bob 3
george 2
sam 1
ralph 1
mary 1
Name: 0, dtype: int64
或者:
s = df.set_index("col1").agg("sum").to_frame().explode(0)
print (s.reset_index().groupby(["index", 0]).size().unstack(0))
0 bob fred george mary ralph sam susie
index
col2 2.0 1.0 1.0 2.0 1.0 NaN 1.0
col3 3.0 NaN 2.0 1.0 1.0 1.0 NaN
您可以在分解前合并列
df['col4']=df['col2']+df['col3']
df.drop(columns = ['col2','col3'],inplace = True)
然后在 'col4'
上爆炸
我想要列表中元素的value_counts,首先你需要展平列,然后以value_counts为例:
import pandas as pd
from itertools import chain
df = pd.DataFrame(data=[
[123456, ['mary', 'ralph', 'bob'], ['bob', 'sam', 'george']],
[456789, ['george', 'fred', 'susie'], ['ralph', 'mary', 'bob']],
[789123, ['mary', 'bob'], ['bob', 'george']]
], columns=['col1', 'col2', 'col3'])
print(pd.Series(chain.from_iterable(df['col2'])).value_counts())
输出
mary 2
bob 2
susie 1
george 1
fred 1
ralph 1
dtype: int64
上面的结果是 value_counts for col2
你的例子。
您可以应用一个函数来获取每一列,flatten
它和 returns 该列的 value_counts
。然后用 0 替换 NaN
值并将返回的帧转换为整数以整理输出:
import pandas as pd
from pandas.core.common import flatten
def nested_valuecounts(series):
flattened = list(flatten(series))
return pd.Series.value_counts(flattened)
out = df[["col2", "col3"]].apply(nested_valuecounts).fillna(0).astype(int)
print(out)
col2 col3
bob 1 3
fred 1 0
george 1 2
mary 2 1
ralph 1 1
sam 0 1
susie 1 0
你可以试试:
df.melt('col1').explode('value')\ #melt col2 and col3 into one column and explode
.groupby(['variable','value'])\ #Groupby melted columns
.count()['col1']\ #count
.unstack(0, fill_value=0) #reshape to show counts per col2 and col3 by name
输出:
variable col2 col3
value
bob 2 3
fred 1 0
george 1 0
mary 2 1
ralph 1 1
sam 0 1
susie 1 0
我在多列中有以下数据:
col1 col2 col3
123456 ['mary','ralph', ''bob'] ['bob','sam']
456789 ['george','fred', susie'] ['ralph','mary', 'bob']
789123 ['mary', bob'] ['bob']
我最终需要在每一列上添加一个 value_counts。为了将所有内容都从列表中删除,我正在尝试爆炸。我可以将值放入它们的列 post-explode,没问题。但是,那些了解 explode 的人都知道,我的 value_counts 会被膨胀,因为在将它应用到多个列时会重复 explode 导致的值
例如,分解产生这个:
col1 col2 col3
123456 mary bob
123456 mary sam
123456 mary george
123456 ralph bob
123456 ralph sam
123456 ralph george...etc.
显然,这会导致每列的准确 value_counts 是我需要的。 我尝试在每一列上循环爆炸,然后在每一列爆炸后匹配第一列和爆炸列并删除重复项,但不起作用。总是喜欢不成为房间里最聪明的人(更多需要学习)所以我把这个问题发给了你 pandas 充满想法的大师。 (看看我在那里做了什么?)。谢谢
我可以 value_counts 除了 col1 之外的所有列的预期输出是这样的:
123456 mary bob
123456 ralph sam
123456 bob george
456789 george ralph
456789 fred mary
456789 susie bob
789123 mary bob
789123 bob george
我们可以使用 stack
展开每个列表,然后使用 cumcount
# if not real lists you'll need `literal_eval
from ast import literal_eval
s = df.set_index('col1').stack().map(literal_eval).explode().to_frame()
df1 = s.set_index(s.groupby(level=[0,1]).cumcount(),append=True).unstack(1).droplevel(0,1)
print(df1)
col2 col3
col1
123456 0 mary bob
1 ralph sam
2 bob george
456789 0 george ralph
1 fred mary
2 susie bob
789123 0 mary bob
1 bob george
IIUC 你可以 apply
而不是循环和分解:
print (df.set_index("col1").apply(pd.Series.explode))
col2 col3
col1
123456 mary bob
123456 ralph sam
123456 bob george
456789 george ralph
456789 fred mary
456789 susie bob
789123 mary bob
789123 bob george
对于不均匀列表:
s = df.set_index("col1").agg("sum").to_frame().explode(0)
print (s.groupby(level=0)[0].apply(pd.Series.value_counts))
col2 mary 2
bob 2
george 1
susie 1
ralph 1
john 1
fred 1
col3 bob 3
george 2
sam 1
ralph 1
mary 1
Name: 0, dtype: int64
或者:
s = df.set_index("col1").agg("sum").to_frame().explode(0)
print (s.reset_index().groupby(["index", 0]).size().unstack(0))
0 bob fred george mary ralph sam susie
index
col2 2.0 1.0 1.0 2.0 1.0 NaN 1.0
col3 3.0 NaN 2.0 1.0 1.0 1.0 NaN
您可以在分解前合并列
df['col4']=df['col2']+df['col3']
df.drop(columns = ['col2','col3'],inplace = True)
然后在 'col4'
我想要列表中元素的value_counts,首先你需要展平列,然后以value_counts为例:
import pandas as pd
from itertools import chain
df = pd.DataFrame(data=[
[123456, ['mary', 'ralph', 'bob'], ['bob', 'sam', 'george']],
[456789, ['george', 'fred', 'susie'], ['ralph', 'mary', 'bob']],
[789123, ['mary', 'bob'], ['bob', 'george']]
], columns=['col1', 'col2', 'col3'])
print(pd.Series(chain.from_iterable(df['col2'])).value_counts())
输出
mary 2
bob 2
susie 1
george 1
fred 1
ralph 1
dtype: int64
上面的结果是 value_counts for col2
你的例子。
您可以应用一个函数来获取每一列,flatten
它和 returns 该列的 value_counts
。然后用 0 替换 NaN
值并将返回的帧转换为整数以整理输出:
import pandas as pd
from pandas.core.common import flatten
def nested_valuecounts(series):
flattened = list(flatten(series))
return pd.Series.value_counts(flattened)
out = df[["col2", "col3"]].apply(nested_valuecounts).fillna(0).astype(int)
print(out)
col2 col3
bob 1 3
fred 1 0
george 1 2
mary 2 1
ralph 1 1
sam 0 1
susie 1 0
你可以试试:
df.melt('col1').explode('value')\ #melt col2 and col3 into one column and explode
.groupby(['variable','value'])\ #Groupby melted columns
.count()['col1']\ #count
.unstack(0, fill_value=0) #reshape to show counts per col2 and col3 by name
输出:
variable col2 col3
value
bob 2 3
fred 1 0
george 1 0
mary 2 1
ralph 1 1
sam 0 1
susie 1 0