col.drop_duplicates() 有更快的替代方法吗?

Posted

技术标签:

【中文标题】col.drop_duplicates() 有更快的替代方法吗?【英文标题】:Is there any faster alternative to col.drop_duplicates()? 【发布时间】:2019-06-09 08:28:19 【问题描述】:

我正在尝试删除我的数据框 (csv) 中的重复数据并获取一个单独的 csv 以显示每列的唯一答案。问题是我的代码已经运行了一天(确切地说是 22 小时)我愿意接受其他一些建议。

我的数据大约有 20,000 行带有标题。我之前曾尝试像 df[col].unique() 一样逐一检查唯一列表,并且不需要那么长时间。

>df = pd.read_csv('Surveydata.csv')
>
>df_uni=df.apply(lambda col: col.drop_duplicates().reset_index(drop=True))
>
>df_uni.to_csv('Surveydata_unique.csv',index=False)

我期望的是具有相同列集但在每个字段中没有任何重复的数据框。前任。如果 df['Rmoisture'] 有 Yes,No,Nan 的组合,它应该只有这 3 个包含在另一个数据帧 df_uni 的同一列中。

编辑:这里是例子 input output

【问题讨论】:

我现在正在删除这个答案,我建议您添加一个示例数据框和一个预期的数据框示例。这将有助于观众想出一个可能的解决方案。 @anky_91 知道了,我只是做了例子。 @AOJkeygen - 值的顺序重要吗? 稍微相关的问题,重构此解决方案以模拟调用 df.drop_duplicates() 的最佳方法是什么。我正在尝试优化包含大量 drop_duplicates() 调用的脚本。 【参考方案1】:

另一种方法:

new_df = []
[new_df.append(pd.DataFrame(df[i].unique(), columns=[i])) for i in df.columns]
new_df = pd.concat(new_df,axis=1)
print(new_df)


   Mass     Length  Material  Special Mark  Special Num  Breaking  \
0    4.0   5.500000     Wood            A         20.0      Yes   
1   12.0   2.600000    Steel          NaN          NaN       No   
2    1.0   3.500000   Rubber            B          5.5      NaN   
3   15.0   6.500000  Plastic            X          6.6      NaN   
4    6.0  12.000000      NaN          NaN          5.6      NaN   
5   14.0   2.500000      NaN          NaN          6.3      NaN   
6    2.0  15.000000      NaN          NaN          NaN      NaN   
7    8.0   2.000000      NaN          NaN          NaN      NaN   
8    7.0  10.000000      NaN          NaN          NaN      NaN   
9    9.0   2.200000      NaN          NaN          NaN      NaN   
10  11.0   4.333333      NaN          NaN          NaN      NaN   
11  13.0   4.666667      NaN          NaN          NaN      NaN   
12   NaN   3.750000      NaN          NaN          NaN      NaN   
13   NaN   1.666667      NaN          NaN          NaN      NaN   

                  Comment  
0        There is no heat  
1                     NaN  
2       Contains moisture  
3   Hit the table instead  
4          A sign of wind  
5                     NaN  
6                     NaN  
7                     NaN  
8                     NaN  
9                     NaN  
10                    NaN  
11                    NaN  
12                    NaN  
13                    NaN  

【讨论】:

哇!这种方法实际上也更快。干杯【参考方案2】:

如果列中值的顺序不重要,请将每列转换为 set 以删除重复项,然后转换为 Series 并通过 concat 连接在一起:

df1 = pd.concat(k: pd.Series(list(set(v))) for k, v in df.to_dict('l').items(), axis=1)

如果顺序很重要:

df1 = pd.concat(col: pd.Series(df[col].unique()) for col in df.columns, axis=1)

在 2k 行中执行 1k 个唯一值

np.random.seed(2019)

#2k rows
df = pd.DataFrame(np.random.randint(1000, size=(20, 2000))).astype(str)


In [151]: %timeit df.apply(lambda col: col.drop_duplicates().reset_index(drop=True))
1.07 s ± 16.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [152]: %timeit pd.concat(k: pd.Series(list(set(v))) for k, v in df.to_dict('l').items(), axis=1)
323 ms ± 2.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [153]: %timeit pd.concat(col: pd.Series(df[col].unique()) for col in df.columns, axis=1)
430 ms ± 4.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

在 2k 行中执行 100 个唯一值

df = pd.DataFrame(np.random.randint(100, size=(20, 2000))).astype(str)

In [155]: %timeit df.apply(lambda col: col.drop_duplicates().reset_index(drop=True))
1.3 s ± 12.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [156]: %timeit pd.concat(k: pd.Series(list(set(v))) for k, v in df.to_dict('l').items(), axis=1)
544 ms ± 3.37 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [157]: %timeit pd.concat(col: pd.Series(df[col].unique()) for col in df.columns, axis=1)
654 ms ± 3.16 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

很好地使用了 set,+1。 :) 非常感谢。我会让每个人都知道它是怎么回事:)

以上是关于col.drop_duplicates() 有更快的替代方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

有更快的lm函数吗

这段代码有啥比 boost mutex 更快的吗?

我都有哪些选择可以让我的 ORDER BY 更快?

GDI GetPixel() 有更快的替代方案吗?

是否有更快的方法来检查是否存在数千个 NSManagedObject 项目?

JavaScript 是不是有更快的反向字符串算法?