【问题标题】:Loop that counts unique values in a pandas df计算熊猫df中唯一值的循环
【发布时间】:2019-02-12 07:17:18
【问题描述】:

我正在尝试创建一个loop 或更有效的过程,它可以count pandas df 中的当前值的数量。目前我正在选择我想要执行该功能的值。

所以对于下面的df,我试图确定两个counts

1) ['u'] 返回 ['Code', 'Area'] 中剩余的相同值的计数。那么剩余多少次相同的值出现。

2) ['On'] 返回当前出现在 ['Area'] 中的值的数量。它通过解析df 以查看这些值是否再次出现来实现这一点。因此,它本质上是展望未来,看看这些值是否会再次出现。

import pandas as pd

d = ({
    'Code' : ['A','A','A','A','B','A','B','A','A','A'],            
    'Area' : ['Home','Work','Shops','Park','Cafe','Home','Cafe','Work','Home','Park'],  
     })

df = pd.DataFrame(data=d)

#Select value
df1 = df[df.Code == 'A'].copy()

df1['u'] = df1[::-1].groupby('Area').Area.cumcount()

ids = [1]
seen = set([df1.iloc[0].Area])
dec = False
for val, u in zip(df1.Area[1:], df1.u[1:]):
    ids.append(ids[-1] + (val not in seen) - dec)
    seen.add(val)
    dec = u == 0
df1['On'] = ids

df1 = df1.reindex(df.index).fillna(df1)

问题是我想对Code 中的所有值运行此脚本。而不是一次选择一个。例如,如果我想在 Code['B'] 上做同样的事情,我将不得不更改:df2 = df1[df1.Code == 'B'].copy() 并再次运行脚本。

如果我在Code 中有很多值,它会变得非常低效。我需要一个loop,它可以在'Code'中找到所有unique值理想情况下,脚本看起来像:

df1 = df[df.Code == 'All unique values'].copy()

预期输出:

  Code   Area    u   On
0    A   Home  2.0  1.0
1    A   Work  1.0  2.0
2    A  Shops  0.0  3.0
3    A   Park  1.0  3.0
4    B   Cafe  1.0  1.0
5    A   Home  1.0  3.0
6    B   Cafe  0.0  1.0
7    A   Work  0.0  3.0
8    A   Home  0.0  2.0
9    A   Park  0.0  1.0

【问题讨论】:

  • 使用pd.unique有什么问题?
  • 想要的输出是什么?
  • @朱利安。我不需要Column 中的总unique 值。它有点复杂。它遍历并确定“当前”打开的unique 值。如,如果稍后出现在 df 上,它们将被计算在内。如果不是,他们不会。所以['u'] 是他们出现的次数。 ['On'] 是多少人。
  • 有多少种不同的面积值?许多?百万?
  • 不超过50。Code一般在5-15之间。但它可以改变哪个是痛苦的部分。所以它可能是ABCDEFGHI 一天和ADEGHKLM 下一天。如果每次在 Code 中的值相同,我就会在这些值上运行脚本。

标签: python pandas loops unique


【解决方案1】:

GroupBysizecumcount 一起使用,您可以构建您的u 系列。

您对On 的逻辑不清楚:这需要澄清。

g = df.groupby(['Code', 'Area'])
df['u'] = g['Code'].transform('size') - (g.cumcount() + 1)

print(df)

  Code   Area  u
0    A   Home  2
1    A   Home  1
2    B  Shops  1
3    A   Park  1
4    B   Cafe  1
5    B  Shops  0
6    A   Home  0
7    B   Cafe  0
8    A   Work  0
9    A   Park  0

【讨论】:

  • 谢谢。我在输出中添加了更多见解和简要描述。这更清楚了吗?
【解决方案2】:

我发现您的“开启”逻辑非常混乱。也就是说,我想我可以重现它:

df["u"] = df.groupby(["Code", "Area"]).cumcount(ascending=False)
df["nunique"] = pd.get_dummies(df.Area).groupby(df.Code).cummax().sum(axis=1)
df["On"] = (df["nunique"] - 
           (df["u"] == 0).groupby(df.Code).cumsum().groupby(df.Code).shift().fillna(0)

这给了我

In [212]: df
Out[212]: 
  Code   Area  u  nunique   On
0    A   Home  2        1  1.0
1    A   Work  1        2  2.0
2    A  Shops  0        3  3.0
3    A   Park  1        4  3.0
4    B   Cafe  1        1  1.0
5    A   Home  1        4  3.0
6    B   Cafe  0        1  1.0
7    A   Work  0        4  3.0
8    A   Home  0        4  2.0
9    A   Park  0        4  1.0

在此,u 是该行之后匹配的(代码、区域)对的数量。 nunique 是迄今为止在该代码中看到的唯一区域值的数量。 On 是到目前为止看到的唯一区域的数量,除了一旦我们“用完”一个区域——一旦它不再被使用——我们就开始从 nuniq 中减去它。

【讨论】:

  • 出色的@DSM。这有点简单。很抱歉造成混乱
猜你喜欢
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
相关资源
最近更新 更多