我有一个伪CSV文件(用管道分隔);有两列,第一列标题是位置,与问题无关。两列中的第二列是标识符(在本例中为用户名)。该文件看起来像这样
Location | Username
San Francisco, CA | sam001040
Chicago, IL | tinytom
New York City, NY | coder23
Palo Alto, CA | sam001040
你可以注意到,sam001040,我在两个城市(旧金山和帕洛阿尔托)看到了。
我需要为用户名分配一个唯一的标识号,并使用新的ID号创建一个新的类似格式的表。映射(用户名 - > id)应存储到磁盘。应该存储映射,因为如果在几天内我可能需要处理另一个文件,那么我可以重用以前存储的映射。
因此在id进程之后文件看起来应该是
Location | Username | UniqueID
San Francisco, CA | sam001040 | 0
Chicago, IL | tinytom | 1
New York City, NY | coder23 | 2
Palo Alto, CA | sam001040 | 0
几天后,这样的文件可以进入
Location | Username
Grand Rapids, MI | gowolves
Chicago, IL | ill
Los Angeles, CA | trojans
Castro Valley, CA | coder23
由于有一些新的用户名,因此需要创建新的标识符,并从上次看到。所以输出的新文件应该是这样的
Location | Username | UniqueID
Grand Rapids, MI | gowolves | 3
Chicago, IL | illini | 4
Los Angeles, CA | trojans | 5
Castro Valley, CA | coder23 | 2
这是一个link to the code,有一些评论,希望名称有用,但我可以澄清一切。
一些警告
其他信息/到目前为止我尝试了什么
主要问题 -
我做错了吗?我整整一周都在看这个,不知道还有什么可做的。我认为处理所有事情的时间不会超过150小时。
如果有人有任何建议或想法,请告诉我!这是我的第一篇文章,所以如果我需要包含更多信息(或删除一些信息),我会提前道歉,并会相应地调整帖子。
答案 0 :(得分:0)
一般情况下,检查某个键是否在字典中时,请执行k in d
,而不是k in d.items()
,这会非常慢,例如
In [68]: d = {x:x+1 for x in range(100000)}
In [69]: %timeit (67 in d)
10000000 loops, best of 3: 39.2 ns per loop
In [70]: %timeit (67 in d.items())
100 loops, best of 3: 10.8 ms per loop
仅此一点就会产生很大的影响。但是,我会使用更像这样的模式,这样可以加快速度。 .map
查找现有用户的ID,.unique()
获取一组新用户名(过滤到查找表中未匹配的用户名)。
df['UserId'] = df['Username'].map(segment_dict)
new_users = df[pd.isnull(df['UserId'])]['Username'].unique()
for u in new_users:
segment_dict[u] = unique_ids
unique_ids += 1
答案 1 :(得分:0)
您可以尝试将User -> ID
映射保留为CSV格式,以便在pandas
中使用。
假设您有一个CSV文件,将已知用户名映射到ID:
$ cat ids.csv
sam001040,0
tinytom,1
coder23,2
您需要处理的新文件newfile.txt
:
$ cat newfile.txt
Location | Username
Grand Rapids, MI | gowolves
Chicago, IL | ill
Los Angeles, CA | trojans
Castro Valley, CA | coder23
您在ids.csv
读到了
ids = pd.read_csv('ids.csv', header=None, index_col=0, names=['Username', 'ID'])
和newfile.txt
:
newfile = pd.read_csv('newfile.txt', sep=' \| ', skipinitialspace=True)
# or pd.read_csv('newfile.txt', sep='|'), which is faster, but won't work nice
# when the file has spaces like you show
现在你可以做到:
newfile_with_ids = newfile.merge(ids, left_on='Username', right_index=True, how='left')
已填写所有已知ID:
Location Username ID
0 Grand Rapids, MI gowolves NaN
1 Chicago, IL ill NaN
2 Los Angeles, CA trojans NaN
3 Castro Valley, CA coder23 2
现在,添加新ID:
mask = newfile_with_ids['ID'].isnull()
ids = pd.concat([ids, pd.DataFrame(
data={'ID': 1 + int(ids.iloc[-1]) + np.arange(mask.sum())},
index=newfile_with_ids.loc[mask, 'Username'].drop_duplicates())])
得到:
ID
Username
sam001040 0
tinytom 1
coder23 2
gowolves 3
ill 4
trojans 5
然后将新ID写入数据帧:
newfile_with_ids.loc[mask, 'ID'] = ids.loc[
newfile_with_ids.loc[mask, 'Username'], 'ID'].values
最后你有:
Location Username ID
3 Castro Valley, CA coder23 2
0 Grand Rapids, MI gowolves 3
1 Chicago, IL ill 4
2 Los Angeles, CA trojans 5
最后,保存新的ids
并继续。