我彻底查看了Stack Overflow,但是找不到任何有用的结果.在这一点上,我甚至不确定这是否可行,但因为我只是一个初学者,我以为我至少会问这里.
基本上,我有多个数据集,每个数据集大约有800万行,我不想循环每一行.我在多个地方读到,使用pandas DataFrames,矢量化几乎总是最快的操作,但我想不出一种在没有循环的情况下编写脚本的方法.速度是至关重要的,因为我宁愿不让我的电脑连续工作一个月.
我必须从一个DataFrame中获取两个值,并将它们用作另一个DataFrame的索引,并将值更改为1.假设以下代码:
>>> import pandas as pd
>>> df1 = pd.DataFrame([[1,2],[3,4],[5,6]])
>>> df1.columns = ['A','B']
>>> df1
A B
0 1 2
1 3 4
2 5 6
>>> df2 = pd.DataFrame(0, index = list(df1['B']), columns = list(df1['A']))
>>> df2
1 3 5
2 0 0 0
4 0 0 0
6 0 0 0
Run Code Online (Sandbox Code Playgroud)
现在,我有一个像这样工作的for循环:
>>> listA = list(df1['A'])
>>> listB = list(df2['B'])
>>> row_count = len(listB)
>>> for index in range(row_count):
... col = listA[index]
... row = listB[index]
... df2[col][row] = 1
Run Code Online (Sandbox Code Playgroud)
在range()迭代器上使用for循环似乎明显快于iterrows().但我试图让我的脚本尽可能快地运行(因为我有大量的数据)所以我想知道我是否可以摆脱循环.我认为pandas模块很可能有一个DataFrames的方法,我不知道它可以非常高效地完成这项工作.
任何帮助表示赞赏.
编辑:可能的重复不解决我的问题,因为我的目标不是将对角线值更改为1; 这只是我的例子中的巧合,因为我有非常简单的DataFrame.另外,如果这不是我应该如何格式化编辑,我很抱歉; 我是这个社区的新手.
我认为你需要pd.get_dummies但首先set_index来自专栏B:
print (df1.set_index('B')['A'])
B
2 1
4 3
6 5
Name: A, dtype: int64
print (pd.get_dummies(df1.set_index('B')['A']))
1 3 5
B
2 1 0 0
4 0 1 0
6 0 0 1
Run Code Online (Sandbox Code Playgroud)
如果重复,需要groupby使用聚合max:
df1 = pd.DataFrame([[1,2],[3,4],[5,6], [1,6]])
df1.columns = ['A','B']
print (df1)
A B
0 1 2
1 3 4
2 5 6
3 1 6
df2 = pd.get_dummies(df1.set_index('B')['A'])
df2 = df2.groupby(level=0).max()
print (df2)
1 3 5
B
2 1 0 0
4 0 1 0
6 1 0 1
Run Code Online (Sandbox Code Playgroud)
由DYZ替代编辑(重置索引并改为引用列):
print(pd.get_dummies(df1.set_index('B')['A']).reset_index().groupb??y('B').max())
Run Code Online (Sandbox Code Playgroud)
答案
#6 是我最好的尝试。
编辑:
对于选项 6,您可以增加而不是覆盖分配。这个小调整应该可以让你计算一下。
df2.values[row_indexers, col_indexers] += 1
Run Code Online (Sandbox Code Playgroud)
选项1
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
df1.groupby(list('AB')).size().gt(0).mul(1) \
.reindex(df2.unstack().index, fill_value=0) \
.unstack(0)
Run Code Online (Sandbox Code Playgroud)
选项2
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
mux = pd.MultiIndex.from_arrays(df1.values.T).drop_duplicates()
df2.update(pd.Series(1, mux).unstack(0))
df2
Run Code Online (Sandbox Code Playgroud)
选项3
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
mux = pd.MultiIndex.from_arrays(df1.values.T).drop_duplicates()
df2.where(pd.Series(False, mux).unstack(0, fill_value=True), 1)
Run Code Online (Sandbox Code Playgroud)
选项4
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
mux = pd.MultiIndex.from_arrays(df1.values.T).drop_duplicates()
df2[pd.Series(True, mux).unstack(0, fill_value=False)] = 1
df2
Run Code Online (Sandbox Code Playgroud)
选项5
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
for i, (a, b) in df1.iterrows():
df2.set_value(b, a, 1)
df2
Run Code Online (Sandbox Code Playgroud)
选项 6
受到 @ayhan 和 @Divakar 的启发
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
row_indexers = df2.index.values.searchsorted(df1.B.values)
col_indexers = df2.columns.values.searchsorted(df1.A.values)
df2.values[row_indexers, col_indexers] = 1
df2
Run Code Online (Sandbox Code Playgroud)
给定示例代码的计时
:
df1 = pd.DataFrame([[1,2], [3,4], [5,6], [1,6]], columns=['A', 'B'])
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
def pir1():
return df1.groupby(list('AB')).size().gt(0).mul(1) \
.reindex(df2.unstack().index, fill_value=0) \
.unstack(0)
def pir2():
mux = pd.MultiIndex.from_arrays(df1.values.T).drop_duplicates()
df2.update(pd.Series(1, mux).unstack(0))
def pir3():
mux = pd.MultiIndex.from_arrays(df1.values.T).drop_duplicates()
return df2.where(pd.Series(False, mux).unstack(0, fill_value=True), 1)
def pir4():
mux = pd.MultiIndex.from_arrays(df1.values.T).drop_duplicates()
df2[pd.Series(True, mux).unstack(0, fill_value=False)] = 1
def pir5():
for i, (a, b) in df1.iterrows():
df2.set_value(b, a, 1)
def pir6():
row_indexers = df2.index.values.searchsorted(df1.B.values)
col_indexers = df2.columns.values.searchsorted(df1.A.values)
df2.values[row_indexers, col_indexers] = 1
return df2
def ayhan1():
row_indexers = [df2.index.get_loc(r_label) for r_label in df1.B]
col_indexers = [df2.columns.get_loc(c_label) for c_label in df1.A]
df2.values[row_indexers, col_indexers] = 1
def jez1():
return pd.get_dummies(df1.set_index('B')['A']).groupby(level=0).max()
Run Code Online (Sandbox Code Playgroud)
更大的示例
代码:
from itertools import combinations
from string import ascii_letters
letter_pairs = [t[0] + t[1] for t in combinations(ascii_letters, 2)]
df1 = pd.DataFrame(dict(A=np.random.randint(0, 100, 10000),
B=np.random.choice(letter_pairs, 10000)))
df2 = pd.DataFrame(0, index = list(df1['B'].unique()),
columns = list(df1['A'].unique()))
Run Code Online (Sandbox Code Playgroud)