【问题标题】:pandas: count things熊猫:数东西
【发布时间】:2012-10-03 17:56:56
【问题描述】:

下文中,male_trips 是大熊猫数据框,站是小熊猫数据框。对于每个车站 ID,我想知道发生了多少次男性旅行。以下内容可以完成这项工作,但需要很长时间:

mc = [ sum( male_trips['start_station_id'] == id ) for id in stations['id'] ]

我应该怎么做呢?


更新!所以有两种主要的方法:groupby(),然后是size(),以及更简单的.value_counts()。我做了一个快速的timeitgroupby 方法以相当大的优势获胜!代码如下:

from timeit import Timer
setup = "import pandas; male_trips=pandas.load('maletrips')"
a  = "male_trips.start_station_id.value_counts()"
b = "male_trips.groupby('start_station_id').size()"
Timer(a,setup).timeit(100)
Timer(b,setup).timeit(100)

结果如下:

In [4]: Timer(a,setup).timeit(100) # <- this is value_counts
Out[4]: 9.709594964981079

In [5]: Timer(b,setup).timeit(100) # <- this is groupby / size
Out[5]: 1.5574288368225098

请注意,在这种速度下,键入 value_counts 会稍微快一些,并且记忆更少!

【问题讨论】:

  • 数据框有多大?你有足够的内存吗?在速度方面,我认为它没有任何问题。
  • @myusuf3 只是为了比较,我上面的方法需要一分钟多的时间(我已经厌倦了数数),而下面 Dani 的解决方案将以毫秒为单位。
  • 这真的很令人惊讶,因为算法.py 中有一个特定的值计数函数,我怀疑如果它不比 groupby 和 size 快,Wes 会添加这个函数。对于刚刚加载的 DataFrame,我得到了不同的结果:在 [20] 中:timeit df.groupby(df.columns[8]).size() 100 个循环,最好的 3:每个循环 13.4 毫秒在 [22]:timeit df [df.columns[8]].value_counts() 100 次循环,最好的 3 次:每次循环 5.62 毫秒。
  • 确保以多个顺序(a 在 b 之前,a 在 b 之后)多次(10 次或更多)运行计时测试。如果你只做了两次测试,可能第一次运行将数据从磁盘加载到磁盘缓冲区中,第二次运行直接从缓冲区中读取数据,从而避免了磁盘访问时间。

标签: python pandas


【解决方案1】:

这需要多长时间:

df = male_trips.groupby('start_station_id').sum()

【讨论】:

  • .sum() 将数据库中的数字列相加。不过,几乎可以完成这项工作!
【解决方案2】:

编辑:在上面的答案中看到isinvalue_counts 存在(value_counts 甚至在pandas.core.algorithmisin 中都有自己的条目,而isin 不仅仅是np.in1d)我更新了以下三种方法

male_trips.start_station_id[male_trips.start_station_id.isin(station.id)].value_counts()

您还可以对stations.id 进行内部连接: pd.merge(male_trips, station, left_on='start_station_id', right_on='id') 后跟 value_counts。 或者:

male_trips.set_index('start_station_id, inplace=True)
station.set_index('id, inplace=True)
male_trips.ix[male_trips.index.intersection(station.index)].reset_index().start_station_id.value_counts()

如果你有时间,我会对它与巨大的 DataFrame 的表现有何不同感兴趣。

【讨论】:

  • 酷。所以 male_trips.start_station_id[male_trips.start_station_id.isin(stations.id)].value_counts() 可以解决问题,尽管可能比 groupby 慢。
  • 合并抱怨“没有名为 start_station_id 的项目”。这种方法是我一直试图找到工作的方法之一,并且经常遇到这个问题。不太清楚这里发生了什么......
  • 重新索引也抱怨,我绝对不确定这里发生了什么。这是错误:重新索引仅对具有唯一值的索引对象有效。
  • 顺便说一句,您刚刚向我展示了 5 个全新的 pandas 概念。谢谢!
  • 这是我的错:“on”仅在两个 DataFrame 中都出现列时使用(所以我的代码指的是 id 和 start_station_id 上的连接,这在这里是错误的)。在这里你必须使用“left_on”和“right_on”。对于重新索引:非唯一索引在 pandas 中相当新。这可能是不支持的。尝试 df.ix[...] 而不是 df.reindex 不会引发此错误。
【解决方案3】:

我会喜欢 Vishal,但不是使用 sum(),而是使用 size() 来计算分配给每组“start_station_id”的行数。所以:

df = male_trips.groupby('start_station_id').size()

【讨论】:

  • 你的解决方法和male_trips.value_counts('start_station_id')一样
【解决方案4】:

我下面的答案适用于 Pandas 0.7.3。不确定新版本。

这就是pandas.Series.value_counts 方法的用途:

count_series = male_trips.start_station_id.value_counts()

然后根据stations['id'] 中的值检查count_series 应该很简单。但是,如果您坚持考虑这些值,则可以执行以下操作:

count_series = (
                male_trips[male_trips.start_station_id.isin(stations.id.values)]
                    .start_station_id
                    .value_counts()
               )

这只会计算在stations.id 中实际找到的电台 ID。

【讨论】:

    【解决方案5】:

    【讨论】:

    • .count() 似乎计算了每列中的所有非空值,这很酷,只是不完全符合我的要求。
    猜你喜欢
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多