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() 有更快的替代方法吗?的主要内容,如果未能解决你的问题,请参考以下文章