Python Pandas duplicated vs groupby标记所有重复值

Python Pandas duplicated vs groupby标记所有重复值,python,pandas,Python,Pandas,我有一个非常简单的需求,这在其他几篇文章中已经出现,但我不确定是使用groupby还是duplicated方法来实现它 除了第一个副本被标记为假而不是真之外,我在下面的副本中有我需要的东西。我需要所有的副本都是真的 我的目标是能够在数据重复时将两列中的数据连接在一起,否则,保持数据不变 样本输入: ID File Name 1 Text.csv 2 TEXT.csv 3 unique.csv 4 unique2.csv 5 text.csv 期望输出: ID File

我有一个非常简单的需求,这在其他几篇文章中已经出现,但我不确定是使用
groupby
还是
duplicated
方法来实现它

除了第一个副本被标记为
而不是
之外,我在下面的
副本中有我需要的东西。我需要所有的副本都是真的

我的目标是能够在数据重复时将两列中的数据连接在一起,否则,保持数据不变

样本输入:

ID  File Name
1   Text.csv
2   TEXT.csv
3   unique.csv
4   unique2.csv
5   text.csv
期望输出:

ID  File Name   LowerFileName   Duplicate   UniqueFileName
1   Text.csv    text.csv    TRUE    1Text.csv
2   TEXT.csv    text.csv    TRUE    2TEXT.csv
3   unique.csv  unique.csv  FALSE   unique.csv
4   unique2.csv unique2.csv FALSE   unique2.csv
5   text.csv    text.csv    TRUE    5text.csv


df_attachment = pd.read_csv("Attachment.csv")
df_attachment['LowerFileName'] = df_attachment['File Name'].str.lower()
df_attachment['Duplicate'] = df_attachment.duplicated('LowerFileName')
#This syntax is incorrect 
df_attachment['UniqueFileName'] = np.where(df_attachment['Duplicate']=='TRUE', pd.concat(df_attachment['ID'],df_attachment['File Name']), df_attachment['File Name'))

对于您的用例,您需要使用groupby:

dupes = df_attachment.groupby('Name').ID.count() > 1
dupes.name = 'Duplicate'
#merge duplicate flage into the original dataframe on the common column 'Name'
df_attachment = pd.merge(df_attachment, dupes.reset_index()) 

也许使用
groupby
lambda
表达式可以实现您的目标:

gb = df.groupby('Lower File Name')['Lower File Name'].count()
duplicates = gb[gb > 1].index.tolist()
df['UniqueFileName'] = \
    df.apply(lambda x: '{0}{1}'.format(x.ID if x['Lower File Name'] in duplicates
                                       else "", x['File Name']), axis=1)

>>> df
   ID    File Name Lower File Name Duplicate   UniqueFileName
0   1     Text.csv        text.csv     False        1Text.csv
1   2     TEXT.csv        text.csv      True        2TEXT.csv
2   3   unique.csv      unique.csv     False      3unique.csv
3   4  unique2.csv     unique2.csv     False  Noneunique2.csv
4   5     text.csv        text.csv      True        5text.csv
5   6   uniquE.csv      unique.csv      True      6uniquE.csv
lambda表达式根据OP的要求生成一个唯一的文件名,方法是仅在
较低的文件名
重复的情况下(即存在多个具有相同小写文件名的文件),使用相关的
ID
预加
文件名。否则,它只使用小写文件名,没有
ID

请注意,此解决方案不使用上述数据帧中的
replicate

另外,简单地将
ID
附加到
较低的文件名
以生成唯一的名称不是更简单吗?假设ID是唯一的,您不需要上述解决方案,甚至不需要检查重复项。

要“绕过”此功能,最简单的方法是使用
df.duplicated(col_name)| df.duplicated(col_name,take_last=True)
生成掩码。按位or表示生成的序列对于所有重复项都是
True

然后使用索引设置从原始名称或数字为fron的新名称中删除的值

在您的情况下,如下所示:

# Generating your DataFrame
df_attachment = pd.DataFrame(index=range(5))
df_attachment['ID'] = [1, 2, 3, 4, 5]
df_attachment['File Name'] = ['Text.csv', 'TEXT.csv', 'unique.csv',
                             'unique2.csv', 'text.csv']
df_attachment['LowerFileName'] = df_attachment['File Name'].str.lower()


# Answer from here, mask generation over two lines for readability
mask = df_attachment.duplicated('LowerFileName')
mask = mask | df_attachment.duplicated('LowerFileName', take_last=True)
df_attachment['Duplicate'] = mask

# New column names if possible
df_attachment['number_name'] = df_attachment['ID'].astype(str) + df_attachment['File Name']

# Set the final unique name column using the mask already generated
df_attachment.loc[mask, 'UniqueFileName'] = df_attachment.loc[mask, 'number_name']
df_attachment.loc[~mask, 'UniqueFileName'] = df_attachment.loc[~mask, 'File Name']

# Drop the intermediate column used
del df_attachment['number_name']
最后的
df_附件

    ID  File Name   LowerFileName   Duplicate   UniqueFileName
0   1   Text.csv    text.csv    True    1Text.csv
1   2   TEXT.csv    text.csv    True    2TEXT.csv
2   3   unique.csv  unique.csv  False   unique.csv
3   4   unique2.csv unique2.csv False   unique2.csv
4   5   text.csv    text.csv    True    5text.csv
此方法使用矢量化操作和索引,因此对于任何大小的数据帧都应该很快

编辑:2017-03-28 昨天有人对此进行了投票,所以我想我可以编辑一下,说自从
0.17.0
以来,熊猫就一直支持这一点,请参见此处的更改:

现在,您可以使用
drop_duplicates
duplicated
keep
参数,并将其设置为
False
以标记所有重复项:

因此,在生成重复列的行上方变成:

df_attachment['Duplicate']=df_attachment.duplicated('LowerFileName',keep=False)
灵感来自您可以做的事情(假设您的
文件名
列重命名为
文件名
):

这给了你:

   ID    File Name  unique_name
0   1     Text.csv     Text.csv
1   2     TEXT.csv    2TEXT.csv
2   3   unique.csv   unique.csv
3   4  unique2.csv  unique2.csv
4   5     text.csv    5text.csv

ID 4所需输出中的LowerFileName不应该是“unique2.csv”吗?谢谢Alexander!我不得不做一个修改,因为它在不重复的文件名后面附加了“None”:
df.apply(lambda x:{0}{1}.format(x.ID,如果x['Lower file Name']是重复的,那么其他'”,x['file Name']),axis=1)
,在所有情况下,只附加ID会容易得多,但不幸的是,必须匹配该格式的另一个文件。很难说是怎么回事。
   ID    File Name  unique_name
0   1     Text.csv     Text.csv
1   2     TEXT.csv    2TEXT.csv
2   3   unique.csv   unique.csv
3   4  unique2.csv  unique2.csv
4   5     text.csv    5text.csv