在python中,如何从任何列中存在特定字符串的数据框中获取行(字符串值)

时间:2019-03-05 05:01:24

标签: python string pandas

我的数据框包含nameageTask1Task2Task3。 现在,我需要在Task1Task2Task3列中获取满足字符串值的所有行。假设我要检查关键字“草稿”。如果“起草”作为任何这些列值的一部分存在,则必须将整行添加到结果框架中。

我尝试过isin(),但我是对还是错。我需要提取包含特定关键字的“ N”行。 我试过了
df.columns[df.Task1.str.contains("Drafting")],但这比较并给出了单列。 任何人都知道如何使用str.contains或任何其他方法来比较列的字符串值并获取所有满足检查条件的行。

  Name  Age              Task1    Task2            Task3
0  Ann   43  Drafting a Letter  sending           paking
1  Juh   29            sending   paking  Letter Drafting
2  Jeo   42            Pasting  sending           paking
3  Sam   59            sending  pasting  Letter Drafting

我需要检查关键字“草稿”是否存在于任何列中[该列包含3到4个单词,需要检查此单词/句子中是否存在草稿];结果应该是:

  Name  Age              Task1    Task2            Task3
0  Ann   43  Drafting a Letter  sending           paking
1  Juh   29            sending   paking  Letter Drafting
3  Sam   59            sending  pasting  Letter Drafting

5 个答案:

答案 0 :(得分:4)

或者只是(请注意,这将检查整个df而不是特定的列):

df[df.astype(str).apply(lambda x: x.str.contains('Drafting')).any(axis=1)]
#for case insensitive use below
#df[df.astype(str).apply(lambda x: x.str.contains('Drafting',case=False)).any(axis=1)]

  Name  Age              Task1    Task2            Task3
0  Ann   43  Drafting a Letter  sending           paking
1  Juh   29            sending   paking  Letter Drafting
3  Sam   59            sending  pasting  Letter Drafting

答案 1 :(得分:3)

对2万行数据的给定答案进行快速比较-

@Alollz(在评论中)

%timeit df.loc[df.filter(like='Task').applymap(lambda x: 'Drafting' in x).any(1)]
25.2 ms ± 2.09 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

@谢尔盖·布什曼诺夫

%timeit df[df.Task1.str.contains("Drafting") | df.Task2.str.contains("Drafting") | df.Task3.str.contains("Drafting")]
58.7 ms ± 9.25 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

@ anky_91

%timeit df[df.filter(like='Task').apply(lambda x: x.str.contains('Drafting')).any(axis=1)]
88.6 ms ± 12.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit df[df.astype(str).apply(lambda x: x.str.contains('Drafting')).any(axis=1)]
128 ms ± 14.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

@ALollz

%timeit  df.loc[df.filter(like='Task').stack().str.split(expand=True).eq('Drafting').any(1).any(level=0)]
290 ms ± 29.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

答案 2 :(得分:1)

您可以尝试:

new_df = df[df.Task1.str.contains("Drafting") | df.Task2.str.contains("Drafting") | df.Task3.str.contains("Drafting")]

这将返回new_df,其中任何“ Task1,2,3”列中的行均包含“草稿”。

答案 3 :(得分:0)

这可以使用np.where来实现:

df = pd.DataFrame({
    'Name': ['Ann', 'Juh', 'Jeo', 'Sam'],
    'Age': [43,29,42,59],
    'Task1': ['Drafting a letter', 'Sending', 'Pasting', 'Sending'],
    'Task2': ['Sending', 'Paking', 'Sending', 'Pasting'],
    'Task3': ['Packing', 'Letter Drafting', 'Paking', 'Letter Drafting']
    })

df_new = df.iloc[df.index[np.concatenate(
                np.where(df['Task1'].str.contains('Drafting')) +
                np.where(df['Task2'].str.contains('Drafting')) +
                np.where(df['Task3'].str.contains('Drafting'))).astype(int)
            ].values.tolist()]

print(df_new)

  Name  Age              Task1    Task2            Task3
0  Ann   43  Drafting a letter  Sending          Packing
1  Juh   29            Sending   Paking  Letter Drafting
3  Sam   59            Sending  Pasting  Letter Drafting

答案 4 :(得分:-2)

您可以尝试这样的事情,

new_df = df[(df['Task1'] == 'Drafting') | (df['Task2'] == 'Drafting') | (df['Task3'] == 'Drafting')]

如果列Task1Task2Task3包含“草稿”,则会选择所有行。