我的代码中包含userID
,categoryID
和date
作为输入值。我想检查条目是否有效,例如如果我的数据集中甚至存在userID
。
它按照我的方式工作,但我必须等待几秒钟(!),直到执行主程序。
var_uid = int(input("Please enter a user ID: "))
var_catid = input("Please enter a category ID: ")
var_date = input("Please enter a date to restrict the considered data (YYYY-MM-DD): ")
if (~var_uid in df_data['UserID'].values) :
print("There is no such user with this UserID. Please enter a different UserID.")
elif (~df_data['CategoryID'].str.contains(var_catid).any()) :
print("There is no such category with this CategoryID. Please enter a different CategoryID")
else:
### I convert my date to datetime object to be able to do some operations with it. ###
date = pd.to_datetime(var_date)
s_all = df_data[df_data.columns[7]]
s_all_datetime = pd.to_datetime(s_all)
df_data['UTCtime'] = s_all_datetime
min_date_str = "2012-04-03"
min_date = pd.to_datetime(min_date_str)
max_date_str = "2013-02-16"
max_date = pd.to_datetime(max_date_str)
if (date < min_date or date > max_date) :
print("There is noch such date. Please enter a different date from 2012-04-03 until 2013-02-16")
else:
some code
我知道,stackoverflow不是用于完成工作,实际上我的代码是有效的。不过,你能否至少给出一些暗示什么是更快的实施?数据框有230k行,如果我的程序必须用每个if子句运行它,那当然不是最好的方法。
我以为我可以提取,例如我的UserID
列的唯一值,将其保存在列表中并使用我的if子句进行检查。
但
df_data['UserID'].unique.tolist()
不起作用。
感谢您的帮助。
/编辑:此处为df_data.info()
和df_data.head()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 227428 entries, 0 to 227427
Data columns (total 8 columns):
UserID 227428 non-null int64
VenueID 227428 non-null object
CategoryID 227428 non-null object
CategoryName 227428 non-null object
Latitude 227428 non-null float64
Longitude 227428 non-null float64
TimezoneOffset 227428 non-null int64
UTCtime 227428 non-null object
dtypes: float64(2), int64(2), object(4)
memory usage: 13.9+ MB
None
目:
UserID VenueID CategoryID CategoryName Latitude Longitude TimezoneOffset UTCtime
0 470 49bbd6c0f964a520f4531fe3 4bf58dd8d48988d127951735 Arts & Crafts Store 40.719810 -74.002581 -240 Tue Apr 03 18:00:09 +0000 2012
1 979 4a43c0aef964a520c6a61fe3 4bf58dd8d48988d1df941735 Bridge 40.606800 -74.044170 -240 Tue Apr 03 18:00:25 +0000 2012
2 69 4c5cc7b485a1e21e00d35711 4bf58dd8d48988d103941735 Home (private) 40.716162 -73.883070 -240 Tue Apr 03 18:02:24 +0000 2012
3 395 4bc7086715a7ef3bef9878da 4bf58dd8d48988d104941735 Medical Center 40.745164 -73.982519 -240 Tue Apr 03 18:02:41 +0000 2012
4 87 4cf2c5321d18a143951b5cec 4bf58dd8d48988d1cb941735 Food Truck 40.740104 -73.989658 -240 Tue Apr 03 18:03:00 +0000 2012
答案 0 :(得分:1)
你是什么意思
但是df_data ['UserID']。unique.tolist()不起作用。
你的意思是命令失败了吗?这可能是因为unique是一个函数,你必须把它叫做
df_data['UserID'].unique().tolist()
或者你的意思是它仍然太慢?在这种情况下,您可能不想使用python列表,因为它仍然必须遍历每个条目。如果您改为使用集合,则最糟糕的情况是O(logn)检索时间。所以
set(df['UserID'].tolist())
现在,这样可以更快地查找用户,但如果类别需要更复杂的内容(如str.contains),您仍需要查看列表。但是,如果类别的基数要小得多,那么你可能只需要对它进行唯一处理并处理较小的列表。
答案 1 :(得分:1)
对于这些包含检查,您应该将User(和Category)设为索引:
if (~var_uid in df_data['UserID'].values) :
elif (~df_data['CategoryID'].str.contains(var_catid).any()) :
一旦这些在索引中(注意:这应该在这个块之外完成,而不是每次都这样做):
df = df_data.set_index(["UserId", "CategoryID"])
然后你可以在O(1)中查找:
user_id in df.index.levels[0]
category_id in df.index.levels[1] # granted this doesn't do the str contains (but that'll always be inefficient)
您可以手动创建这些内容,您必须再次执行一次,而不是每次查找都能获得好处:
pd.Index(df_date["UserID"])
# if lots of non-unique users this will be more space efficient
pd.Index(df_date["UserID"].unique())
答案 2 :(得分:1)
考虑创建查找索引,然后获得对数速度访问。这是一个例子:
import pandas as pd
import numpy as np
n = int(1e6)
np.random.seed(0)
df = pd.DataFrame({
'uid': np.arange(n),
'catid': np.repeat('foo bar baz', n),
})
速度较慢的版本:
>>> %timeit for i in range(n // 2, n // 2 + 1000): i in df.uid.values
1 loop, best of 3: 2.32 s per loop
但是,您可以预先计算索引:
>>> uids = pd.Index(df.uid.values)
>>> %timeit for i in range(n // 2, n//2 + 1000): i in uids
1000 loops, best of 3: 412 µs per loop
哇,那太快了。让我们看看创建索引需要多长时间:
>>> %timeit uids = pd.Index(df.uid.values)
10000 loops, best of 3: 22.5 µs per loop
你也可以使用set
(虽然对于像UserID
这样的整数,使用pandas Index的速度更快,例如对于CategoryID
,您可以预先计算:
>>> catids = set(s for catid in df.catid.values for s in catid.split())
然后检查
>>> catid in catids
这会更快。
答案 3 :(得分:0)
非常感谢所有贡献者!对于我的UserID
我使用了解决方案并将其设置为索引。对于我的CategoryID
,我创建了该集并将其存储在我的程序中。
另外,我发现了另一个更糟糕的瓶颈:
s_all = df_data[df_data.columns[7]]
s_all_datetime = pd.to_datetime(s_all)
df_data['UTCtime'] = s_all_datetime
它将我的'UTCtime'
列转换为datetime对象...用它进行230k次迭代... ^^
我刚刚做了一次,现在存储了新的数据帧。只需每次加载.csv,但速度要快得多。