我有一个大型csv文件,其中的行看起来像
0,1
1,2
3,0
我需要对其进行转换,以便从0开始连续编号。在这种情况下,以下内容可以正常工作
import csv
names = {}
counter = 0
with open('foo.csv', 'rb') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
if row[0] in names:
id1 = row[0]
else:
names[row[0]] = counter
id1 = counter
counter += 1
if row[1] in names:
id2 = row[1]
else:
names[row[1]] = counter
id2 = counter
counter += 1
print id1, id2
我目前的代码如下:
startAP
Python dicts遗憾地使用了大量内存,而且我的输入很大。
当输入太大而dict不适合内存时,我该怎么办
如果有更好/更快的方法来解决这个问题,我也会感兴趣。
答案 0 :(得分:6)
df = pd.DataFrame([['a', 'b'], ['b', 'c'], ['d', 'a']])
v = df.stack().unique()
v.sort()
f = pd.factorize(v)
m = pd.Series(f[0], f[1])
df.stack().map(m).unstack()
答案 1 :(得分:3)
更新:这是一个内存保存解决方案,可将您的所有字符串转换为数字类别:
In [13]: df
Out[13]:
c1 c2
0 stringa stringb
1 stringb stringc
2 stringd stringa
3 stringa stringb
4 stringb stringc
5 stringd stringa
6 stringa stringb
7 stringb stringc
8 stringd stringa
In [14]: x = (df.stack()
....: .astype('category')
....: .cat.rename_categories(np.arange(len(df.stack().unique())))
....: .unstack())
In [15]: x
Out[15]:
c1 c2
0 0 1
1 1 2
2 3 0
3 0 1
4 1 2
5 3 0
6 0 1
7 1 2
8 3 0
In [16]: x.dtypes
Out[16]:
c1 category
c2 category
dtype: object
OLD回答:
我认为您可以对列进行分类:
In [63]: big.head(15)
Out[63]:
c1 c2
0 stringa stringb
1 stringb stringc
2 stringd stringa
3 stringa stringb
4 stringb stringc
5 stringd stringa
6 stringa stringb
7 stringb stringc
8 stringd stringa
9 stringa stringb
10 stringb stringc
11 stringd stringa
12 stringa stringb
13 stringb stringc
14 stringd stringa
In [64]: big.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 30000000 entries, 0 to 29999999
Data columns (total 2 columns):
c1 object
c2 object
dtypes: object(2)
memory usage: 457.8+ MB
所以big
DF有30M行,它的大小是大约。 460MiB ...
让我们对它进行分类:
In [65]: cat = big.apply(lambda x: x.astype('category'))
In [66]: cat.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 30000000 entries, 0 to 29999999
Data columns (total 2 columns):
c1 category
c2 category
dtypes: category(2)
memory usage: 57.2 MB
现在只需57MiB,看起来完全一样:
In [69]: cat.head(15)
Out[69]:
c1 c2
0 stringa stringb
1 stringb stringc
2 stringd stringa
3 stringa stringb
4 stringb stringc
5 stringd stringa
6 stringa stringb
7 stringb stringc
8 stringd stringa
9 stringa stringb
10 stringb stringc
11 stringd stringa
12 stringa stringb
13 stringb stringc
14 stringd stringa
让我们将它的大小与类似的数字DF进行比较:
In [67]: df = pd.DataFrame(np.random.randint(0,5,(30000000,2)), columns=list('ab'))
In [68]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 30000000 entries, 0 to 29999999
Data columns (total 2 columns):
a int32
b int32
dtypes: int32(2)
memory usage: 228.9 MB
答案 2 :(得分:3)
如果您需要一系列ID,请使用factorize
:
df = pd.read_csv(data, header=None, prefix='Col_')
print (pd.factorize(np.hstack(df.values)))
(array([0, 1, 1, 2, 3, 0]), array(['stringa', 'stringb', 'stringc', 'stringd'], dtype=object))
编辑:(根据评论)
您可以获取factorize
方法后获得的元组切片,并相应地映射到整个dataframe
,如下所示相互替换:
num, letter = pd.factorize(np.hstack(df.values))
df.replace(to_replace=sorted(list(set(letter))), value=sorted(list(set(num))))
Col_0 Col_1
0 0 1
1 1 2
2 3 0