Недавно я начал работать с пандами, и я наткнулся на (вероятно, тривиальную) проблему, которую я не могу решить. Чтобы сделать это в чистом сценарии Python, я действительно хочу его в пандах. Вот мой вопрос новобранец.
Имея блок данных ниже:
ID Sample1 quality1 Sample2 quality2 Sample3 quality3
ID1 val str1,str2,str3@num val str1,str2,str3@num val str1,str2,str3@num
ID2 val str4,str5,str63@num val str4,str5,st63@num val str4,str5,str63@num
ID3 val str1,str2,str3@num val str1,str1,str3@num val str4,str2,str3@num
ID4 val str1,str2,str3@num val str2,str2,str3@num val str1,str2,str3@num
ID5 val str4,str5,str63@num val str4,str5,st63@num val str4,str5,str63@num
Я хочу написать функцию, чтобы сохранить только строки, которые имеют минимально необходимое количество показателей качества по n столбцам. На самом деле важна только первая часть строки, поэтому сначала выберите только первую часть строки:
ID Sample1 quality1 Sample2 quality2 Sample3 quality3
ID1 val str1 val str1 val str1
ID2 val str4 val str4 val str4
ID3 val str1 val str1 val str4
ID4 val str1 val str2 val str1
ID5 val str4 val str3 val str4
Предположим, что я хочу сохранить строки с минимальным счетом "str4" в двух столбцах, я бы, вероятно, вычислил процент по столбцам:
ID Sample1 quality1 Sample2 quality2 Sample3 quality3
ID2 val str4 val str4 val str4
ID5 val str4 val str3 val str4
Вот как я начал играть с ним, чтобы знать, где все происходит, но я все еще не могу собрать вещи вместе:
for i,rows in enumerate(table_test.values):
min_val = "str4"
scores = rows[2::2]
lists = np.ndarray.tolist(scores)
for list in lists:
first_str = list.split(",")
print(i, first_str[0])
Спасибо за мысли и/или помощь!
Используйте boolean indexing
для фильтрации с булевой маской:
min_val = "str4"
df = df[df.filter(like='quality').apply(lambda x: x.str.startswith(min_val)).sum(axis=1) >= 2]
print (df)
ID Sample1 quality1 Sample2 quality2 Sample3 \
1 ID2 val str4,str5,str63@num val str4,str5,st63@num val
4 ID5 val str4,str5,str63@num val str4,str5,st63@num val
quality3
1 str4,str5,str63@num
4 str4,str5,str63@num
Или же:
min_val = "str4"
df = df[df.filter(like='quality').applymap(lambda x: x.startswith(min_val)).sum(axis=1) >= 2]
print (df)
ID Sample1 quality1 Sample2 quality2 Sample3 \
1 ID2 val str4,str5,str63@num val str4,str5,st63@num val
4 ID5 val str4,str5,str63@num val str4,str5,st63@num val
quality3
1 str4,str5,str63@num
4 str4,str5,str63@num
Объяснение:
Сначала filter
все столбцы с строкой quality
:
print (df.filter(like='quality'))
quality1 quality2 quality3
0 str1,str2,str3@num str1,str2,str3@num str1,str2,str3@num
1 str4,str5,str63@num str4,str5,st63@num str4,str5,str63@num
2 str1,str2,str3@num str1,str1,str3@num str4,str2,str3@num
3 str1,str2,str3@num str2,str2,str3@num str1,str2,str3@num
4 str4,str5,str63@num str4,str5,st63@num str4,str5,str63@num
Сравните все столбцы с помощью startswith
для boolean DataFrame
:
print (df.filter(like='quality').apply(lambda x: x.str.startswith(min_val)))
quality1 quality2 quality3
0 False False False
1 True True True
2 False False True
3 False False False
4 True True True
Count True
значения по sum
- True
- это процессы, такие как 1
с:
print (df.filter(like='quality').apply(lambda x: x.str.startswith(min_val)).sum(axis=1))
0 0
1 3
2 1
3 0
4 3
dtype: int64
Сравнить по treshold:
print (df.filter(like='quality').apply(lambda x: x.str.startswith(min_val)).sum(axis=1) >=2)
0 False
1 True
2 False
3 False
4 True
dtype: bool
Если хотите также разделять столбцы quality
сначала split
все столбцы quality
и назначать обратно:
min_val = "str4"
cols = df.filter(like='quality').columns
df[cols] = df[cols].apply(lambda x: x.str.split(',').str[0])
#another solution
#df[cols] = df[cols].applymap(lambda x: x.split(',')[0])
print (df)
ID Sample1 quality1 Sample2 quality2 Sample3 quality3
0 ID1 val str1 val str1 val str1
1 ID2 val str4 val str4 val str4
2 ID3 val str1 val str1 val str4
3 ID4 val str1 val str2 val str1
4 ID5 val str4 val str4 val str4
Затем сравните с помощью min_val
для логического DataFrame и фильтруйте так же, как и раньше:
df = df[(df[cols] == min_val).sum(axis=1) >=2]
print (df)
ID Sample1 quality1 Sample2 quality2 Sample3 quality3
1 ID2 val str4 val str4 val str4
4 ID5 val str4 val str4 val str4