熊猫根据多列中的年份列表计算总年份



给定此示例数据集:

id    col1                    col2                 col3
0    [1999, 2000, 2001]   [1989, 2000, 2005]   [1999, 2004, 2005]

我正在尝试创建第四列,其中包含其他三列中每个列表中不同年份的总数。因此,类似于将所有这些列表组合在一起,然后获取len(list(set(所有col列表的组合列表((,在这种情况下,得到以下输出:

id    col1                    col2                 col3               total_years
0    [1999, 2000, 2001]   [1989, 2000, 2005]   [1999, 2004, 2005]        6

我可以生成单独的列来计算每个列表中的所有值,但简单地取所有列列表的十个值的总和,会给出错误的值,因为有些列表中的年份重复。

理想的操作是将所有列表合并为一个列表,然后从中得到一个集合,以及在我看来这个集合的长度。但是,我不知道这在熊猫身上会如何工作。

有一次尝试没有成功:

for col in df.columns[1:]:
new_col = str(col) + "_length"
df[new_col] = df[col].apply(len)
df['new_col_name'] = df.iloc[:,9:].sum(axis=1)

将所有列列表合并为一列中的单个列表后的第二次尝试。我试着得到那一列的长度,不,没用。

df['Total_years'] = len(set(total_lst_col))

stack将所有列表合并为一列,然后合并为explode。然后可以沿着原始索引groupby+nunique。即使你有一年没有list,这也会起作用。

import pandas as pd
df = pd.DataFrame({'id': ['A', 'B', 'C'],
'col1': [[1999, 2000, 2001], [1999, 2001], 2000],
'col2': [[1989, 2000, 2005], [1989, 2000, 2005], [2001, 2002]],
'col3': [[1999, 2004, 2005], [1999], [2005]]})
#.iloc[:, 1:] to ignore the `id` column
df['total_years'] = df.iloc[:, 1:].stack().explode().groupby(level=0).nunique()
id                col1                col2                col3  total_years
0  A  [1999, 2000, 2001]  [1989, 2000, 2005]  [1999, 2004, 2005]            6
1  B        [1999, 2001]  [1989, 2000, 2005]              [1999]            5
2  C                2000        [2001, 2002]              [2005]            4

这里有一个解释:

第一个stack步骤将所有内容放入一个具有MultiIndex的系列中,第0级是原始DataFrame索引,第1级是它所属的列(我们并不真正关心(。

df.iloc[:, 1:].stack()
0  col1    [1999, 2000, 2001]
col2    [1989, 2000, 2005]
col3    [1999, 2004, 2005]
1  col1          [1999, 2001]
col2    [1989, 2000, 2005]
col3                [1999]
2  col1                  2000
col2          [2001, 2002]
col3                [2005]

explode然后将这些列表扩展为每个值一行,并保持非列表值不变。对于相同列表的每个元素,重复上述系列的索引

df.iloc[:, 1:].stack().explode()
0  col1    1999    # index `0` `col1` had 3 elements in
col1    2000    # the list which get expanded to 
col1    2001    # these three rows
col2    1989
...
2  col1    2000    # This value wasn't a list, explode keeps as is
col2    2001
col2    2002
col3    2005

最后,.groupby(level=0)在该级别上分组,,该级别基于原始DataFrame索引,我们计算唯一值的数量,基于该系列的唯一值是在这些列中的任何列中找到的唯一年份。

您可以在每行上使用apply

  • chain所有子列表合一
  • set保留uniques
  • len获取计数
from itertools import chain
df['total_years'] = df.apply(lambda x: len(set(chain(*x))), axis=1)

最新更新