是否可以在分配时进行数组操作?

spi*_*kin 6 python pandas

我彻底查看了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.另外,如果这不是我应该如何格式化编辑,我很抱歉; 我是这个社区的新手.

jez*_*ael 5

我认为你需要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)


piR*_*red 3

答案
#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)

在此输入图像描述