expr使用

本文详细介绍了Linux下expr命令的使用方法,包括字符串匹配、索引查找、子字符串截取、长度计算、算术运算、比较操作及逻辑连接等功能,并通过实例演示了如何正确使用这些功能。
下面将使用示例来介绍expr的用法,在介绍之前,需要注意三点:
(1).数值表达式("+ - * / %")和比较表达式("< <= = == != >= >")会先将两端的参数转换为数值,转换失败将报错。所以可借此来判断参数或变量是否为整数。
(2).expr中的很多符号需要转义或使用引号包围。
(3).所有操作符的两边,都需要有空格。
以下是expr示例。

(1).“string : REGEX"字符串匹配示例。要输出匹配到的字符串结果,需要使用”(“和”)",否则返回的将是匹配到的字符串数量。

[root@xuexi ~]# expr abcde : 'ab\(.*\)'
cde

[root@xuexi ~]# expr abcde : 'ab\(.\)'
c

[root@xuexi ~]# expr abcde : 'ab.*'  
5

[root@xuexi ~]# expr abcde : 'ab.'   
3

[root@xuexi ~]# expr abcde : '.*cd*'
4

注意,由于REGEX中隐含了"^",所以使得匹配时都是从string首字符开始的。

[root@xuexi ~]# expr abcde : 'cd.*'  
0

之所以为0,是因为真正的正则表达式是"^cd.*",而abcde不是c开头而是a开头的,所以无法匹配到任何结果。因此,任何字符串匹配时,都应该从首字符开始。

字符串匹配时,会先将两端参数转换为字符格式。

(2)."index string chars"用法示例。

该表达式是从string中搜索chars中某个字符的位置,这个字符是string中最靠前的字符。例如:

[root@xuexi ~]# expr index abcde dec
3

该命令将对字符串"dec"逐字符分解,首先分解得到第一个字符d,从abcde中搜索到d的位置为4,再分解得到第二个字符e,该字符在abcde中的位置为5,最后得到的字符是c,该字符在abcde中的位置为3。其中3是最靠前的字符,所以命令返回的结果为3。

[root@xuexi ~]# expr index abcde xdc
3

如果chars中的所有字符都不存在于string中,则返回0。

[root@xuexi ~]# expr index abcde 1
0

[root@xuexi ~]# expr index abcde 1x
0

(3)."substr string pos len"用法示例。

该表达式是从string中取出从pos位置开始长度为len的子字符串。如果pos或len为非正整数时,将返回空字符串。

[root@xuexi ~]# expr substr abcde 2 3
bcd

[root@xuexi ~]# expr substr abcde 2 4
bcde

[root@xuexi ~]# expr substr abcde 2 5
bcde

[root@xuexi ~]# expr substr abcde 2 0

[root@xuexi ~]# expr substr abcde 2 -1

(4)."length string"用法示例。该表达式是返回string的长度,其中string不允许为空,否则将报错,所以可以用来判断变量是否为空。

[root@xuexi ~]# expr length abcde
5

[root@xuexi ~]# expr length 111
3

[root@xuexi ~]# expr length $xxx
expr: syntax error

[root@xuexi ~]# if [ $? -ne 0 ];then echo '$xxx is null';fi
$xxx is null

(5)."+ token"用法示例。

expr中有些符号和关键字有特殊意义,如"match"、“index”、“length”,如果要让其成为字符,使用该表达式将任意token强制解析为普通字符串。

[root@xuexi ~]# expr index index d
expr: syntax error

[root@xuexi ~]# expr index length g
expr: syntax error

[root@xuexi ~]# expr index + length g
4

对值为关键字的变量来说,则无所谓。

[root@xuexi ~]# len=lenght

[root@xuexi ~]# expr index $len g
4

(6).算术运算用法示例。

[root@xuexi ~]# expr 1 + 2
3

[root@xuexi ~]# a=3
[root@xuexi ~]# b=4

[root@xuexi ~]# expr $a + $b
7

[root@xuexi ~]# expr 4 + $a
7

[root@xuexi ~]# expr $a - $b
-1

算术乘法符号"*"因为是shell的元字符,所以要转义,可以使用引号包围,或者使用反斜线。

[root@xuexi ~]# expr $a * $b
expr: syntax error

[root@xuexi ~]# expr $a '*' $b
12

[root@xuexi ~]# expr $a \* $b
12

[root@xuexi ~]# expr $b / $a    # 除法只能取整数
1

[root@xuexi ~]# expr $b % $a
1

任意操作符两端都需要有空格,否则:

[root@xuexi ~]# expr 4+$a 
4+3

[root@xuexi ~]# expr 4 +$a
expr: syntax error

由于expr在进行算术运算时,首先会将操作符两边的参数转换为整数,任意一端转换失败都将会报错,所以可以用来判断参数或变量是否为整数。

[root@xuexi ~]# expr $a + $c
expr: non-integer argument

[root@xuexi ~]# if [ $? != 0 ];then echo '$a or $c is non-integer';fi          
$a or $c is non-integer

(7).比较操作符< <= = == != >= >用法示例。其中"<“和”>“是正则表达式正的锚定元字符,且”<"会被shell解析为重定向符号,所以需要转义或用引号包围。

这些操作符会首先会将两端的参数转换为数值,如果转换成功,则采用数值比较,如果转换失败,则按照字符集的排序规则进行字符大小比较。比较的结果若为true,则expr返回1,否则返回0。

[root@xuexi ~]# a=3

[root@xuexi ~]# expr $a = 1
0

[root@xuexi ~]# expr $a = 3
1

[root@xuexi ~]# expr $a \* 3 = 9
1

[root@xuexi ~]# expr abc \> ab
1

[root@xuexi ~]# expr akc \> ackd
1

(8).逻辑连接符号"&“和”|"用法示例。这两个符号都需要转义,或使用引号包围。

"&"表示如果两个参数都非0,则返回第一个参数,否则返回0。但任意一个参数为空,则expr报错。除非空字符串使用引号包围,则处理方法和0一样。 "|"表示如果第一个参数非0,则返回第一个参数的值,否则返回第二个参数。但如果任意一个参数为空,则expr报错。除非空字符串使用引号包围,则处理方法和0一样。
[root@xuexi ~]# expr $abc '|' 1
expr: syntax error

[root@xuexi ~]# expr "$abc" '|' 1
1

[root@xuexi ~]# expr "$abc" '&' 1 
0

[root@xuexi ~]# expr $abc '&' 1 
expr: syntax error

[root@xuexi ~]# expr 0 '&' abc
0

[root@xuexi ~]# expr abc '&' 0
0

[root@xuexi ~]# expr abc '|' 0
abc

[root@xuexi ~]# expr 0 '|' abc  
abc

[root@xuexi ~]# expr abc '&' cde
abc

[root@xuexi ~]# expr abc '|' cde
abc
import re import pandas as pd def map_sample_to_patient_id(sample_ids): “”" 高效精确映射样本ID到病人ID 参数: sample_ids (list): 样本ID列表 返回: tuple: (映射字典, 病人ID列表) """ mapping_dict = {} patient_ids = set() # 优化正则表达式匹配 pattern = r'^aml_ohsu_2018_(\d+)-(\d+)$' for sample_id in sample_ids: # 处理非字符串ID if not isinstance(sample_id, str): mapping_dict[sample_id] = sample_id continue match = re.match(pattern, sample_id) if match: # 提取病人编号并转换为整数(自动去前导零) patient_num = int(match.group(2)) # 构建标准病人ID patient_id = f"aml_ohsu_2018_{patient_num}" mapping_dict[sample_id] = patient_id patient_ids.add(patient_id) else: # 记录无法解析的ID mapping_dict[sample_id] = sample_id return mapping_dict, list(patient_ids) def align_patient_data(expr_data, meta_data, patient_id_col=“PATIENT_ID”): “”" 对齐基因表达数据和元数据 参数: expr_data (DataFrame): 基因表达数据(行:基因,列:样本ID) meta_data (DataFrame): 病人元数据 patient_id_col (str): 元数据中病人ID的列名 返回: DataFrame: 对齐后的基因表达数据 """ # 1. 映射样本ID到病人ID sample_ids = expr_data.columns.tolist() mapping_dict, expr_patient_ids = map_sample_to_patient_id(sample_ids) # 2. 重命名列 expr_renamed = expr_data.rename(columns=mapping_dict) # 3. 分组聚合(同病人多个样本取平均值) # 按列分组(转置后按行分组) patient_expr = expr_renamed.T.groupby(level=0).mean().T # 4. 获取元数据中的病人ID meta_patient_ids = meta_data[patient_id_col].unique().tolist() # 5. 诊断报告 missing_in_expr = set(meta_patient_ids) - set(patient_expr.columns) missing_in_meta = set(patient_expr.columns) - set(meta_patient_ids) print(f"元数据病人总数: {len(meta_patient_ids)}") print(f"表达数据病人总数: {len(patient_expr.columns)}") print(f"在元数据但不在表达数据中的病人数: {len(missing_in_expr)}") print(f"在表达数据但不在元数据中的病人数: {len(missing_in_meta)}") if missing_in_expr: print("前5个缺失病人示例:", list(missing_in_expr)[:5]) # 6. 按元数据顺序对齐 aligned_expr = patient_expr.reindex(columns=meta_patient_ids) return aligned_expr 使用示例 if name == “main”: # 加载数据 (替换为实际路径) expr_file = “gene_expression.csv” meta_file = “patient_metadata.csv” # 读取基因表达数据 # 假设第一列是基因名,列名是样本ID expr_data = pd.read_csv(expr_file, index_col=0) # 读取元数据 meta_data = pd.read_csv(meta_file) # 对齐数据 aligned_data = align_patient_data(expr_data, meta_data) # 保存结果 output_file = "aligned_gene_expression.csv" aligned_data.to_csv(output_file) print(f"对齐后的数据已保存至: {output_file}") # 显示诊断信息 print(f"最终数据维度: {aligned_data.shape}") print(f"包含NaN值的病人数: {aligned_data.isna().any().sum()}") 保存按出现在元数据和表达数据中的全部病人ID
最新发布
09-30
<think>我们想要保存同时出现在元数据和表达数据中的病人ID(即交集),并输出一个包含这些病人ID的列表(或文件)。 但注意:在之前的对齐函数中,我们返回的是按元数据顺序排列的表达数据,其中可能包含NaN列(元数据中存在但表达数据中不存在的病人)。 现在我们需要的是两个数据集中都出现的病人ID。 我们可以修改对齐函数,使其返回交集列表,或者单独写一个函数来获取交集。 考虑到代码复用,我们可以在对齐函数中增加一个返回交集的选项,但为了单一职责原则,我们单独写一个函数来获取共同病人ID。 我们将创建一个新函数,该函数输入为表达数据和元数据(以及病人ID列名),输出为共同病人ID的列表。 同时,我们也希望提供诊断信息(如共同病人数量等)。 另外,我们可能希望将这个共同病人ID列表保存到文件中。 我们将创建一个函数:get_common_patients(expr_data, meta_data, patient_id_col="PATIENT_ID") 返回:共同病人ID列表(已排序),以及一些诊断信息(可选)。 注意:表达数据中的病人ID是通过样本ID映射得到的,并且已经进行了聚合(每个病人一个列)。但是,在求共同病人时,我们实际上不需要聚合表达数据,因为同一个病人的多个样本映射到同一个病人ID,我们只需要知道这个病人ID是否存在即可。 因此,我们可以这样做: 1. 从表达数据的列(样本ID)映射得到病人ID集合(去重)。 2. 从元数据中获取病人ID集合(去重)。 3. 求两个集合的交集,然后返回排序后的列表。 但是注意:表达数据中可能有同一个病人的多个样本,但映射后病人ID是唯一的,所以用集合没问题。 我们来写这个函数: </think>### 保存同时出现在元数据和表达数据中的全部病人ID 以下是优化后的代码,它会精确保存同时出现在元数据和表达数据中的所有病人ID: ```python import re import pandas as pd import numpy as np import os def map_sample_to_patient_id(sample_ids): """ 高效精确映射样本ID到病人ID 参数: sample_ids (list): 样本ID列表 返回: tuple: (映射字典, 病人ID列表) """ mapping_dict = {} patient_ids = set() # 优化正则表达式匹配 pattern = r'^aml_ohsu_2018_(\d+)-(\d+)$' for sample_id in sample_ids: # 处理非字符串ID if not isinstance(sample_id, str): mapping_dict[sample_id] = sample_id continue match = re.match(pattern, sample_id) if match: # 提取病人编号并转换为整数(自动去前导零) patient_num = int(match.group(2)) # 构建标准病人ID patient_id = f"aml_ohsu_2018_{patient_num}" mapping_dict[sample_id] = patient_id patient_ids.add(patient_id) else: # 记录无法解析的ID mapping_dict[sample_id] = sample_id return mapping_dict, list(patient_ids) def save_common_patients(expr_data, meta_data, patient_id_col="PATIENT_ID", output_dir="results"): """ 保存同时出现在表达数据和元数据中的病人ID 参数: expr_data (DataFrame): 基因表达数据 meta_data (DataFrame): 病人元数据 patient_id_col (str): 元数据中病人ID的列名 output_dir (str): 输出目录 返回: tuple: (共同病人列表, 诊断信息字典) """ # 创建输出目录 os.makedirs(output_dir, exist_ok=True) # 1. 从表达数据中提取病人ID sample_ids = expr_data.columns.tolist() _, expr_patients = map_sample_to_patient_id(sample_ids) expr_patient_set = set(expr_patients) # 2. 从元数据中提取病人ID meta_patients = meta_data[patient_id_col].unique().tolist() meta_patient_set = set(meta_patients) # 3. 计算共同病人ID common_patients = sorted(expr_patient_set & meta_patient_set) # 4. 保存结果 # 保存为CSV文件 csv_path = os.path.join(output_dir, "common_patients.csv") pd.DataFrame(common_patients, columns=["patient_id"]).to_csv(csv_path, index=False) # 保存为文本文件(每行一个ID) txt_path = os.path.join(output_dir, "common_patients.txt") with open(txt_path, 'w') as f: f.write("\n".join(common_patients)) # 5. 诊断信息 diagnostic_info = { "meta_count": len(meta_patient_set), "expr_count": len(expr_patient_set), "common_count": len(common_patients), "csv_path": csv_path, "txt_path": txt_path } print(f"元数据病人总数: {diagnostic_info['meta_count']}") print(f"表达数据病人总数: {diagnostic_info['expr_count']}") print(f"共同病人数量: {diagnostic_info['common_count']}") print(f"覆盖率: {diagnostic_info['common_count']/diagnostic_info['meta_count']:.2%}") print(f"结果已保存至: {csv_path} 和 {txt_path}") return common_patients, diagnostic_info def align_and_save_patient_data(expr_data, meta_data, patient_id_col="PATIENT_ID", output_dir="results"): """ 对齐基因表达数据并保存共同病人ID 参数: expr_data (DataFrame): 基因表达数据 meta_data (DataFrame): 病人元数据 patient_id_col (str): 元数据中病人ID的列名 output_dir (str): 输出目录 返回: DataFrame: 对齐后的基因表达数据 """ # 1. 映射样本ID到病人ID sample_ids = expr_data.columns.tolist() mapping_dict, expr_patient_ids = map_sample_to_patient_id(sample_ids) # 2. 重命名列 expr_renamed = expr_data.rename(columns=mapping_dict) # 3. 分组聚合(同病人多个样本取平均值) patient_expr = expr_renamed.T.groupby(level=0).mean().T # 4. 获取共同病人ID common_patients, diag_info = save_common_patients(expr_data, meta_data, patient_id_col, output_dir) # 5. 筛选共同病人的表达数据 common_expr = patient_expr[list(set(patient_expr.columns) & set(common_patients))] # 6. 按元数据顺序对齐 aligned_expr = common_expr.reindex(columns=common_patients) # 7. 保存对齐后的表达数据 aligned_path = os.path.join(output_dir, "aligned_gene_expression.csv") aligned_expr.to_csv(aligned_path) print(f"对齐后的表达数据已保存至: {aligned_path}") print(f"最终数据维度: {aligned_expr.shape}") return aligned_expr # 使用示例 if __name__ == "__main__": # 加载数据 (替换为实际路径) expr_file = "gene_expression.csv" meta_file = "patient_metadata.csv" output_dir = "processed_results" # 读取基因表达数据 expr_data = pd.read_csv(expr_file, index_col=0) # 读取元数据 meta_data = pd.read_csv(meta_file) # 对齐数据并保存共同病人信息 aligned_data = align_and_save_patient_data( expr_data, meta_data, patient_id_col="PATIENT_ID", output_dir=output_dir ) # 可选:筛选共同病人的元数据 common_patients = pd.read_csv(os.path.join(output_dir, "common_patients.csv"))['patient_id'].tolist() common_meta = meta_data[meta_data['PATIENT_ID'].isin(common_patients)] # 保存筛选后的元数据 meta_path = os.path.join(output_dir, "common_patient_metadata.csv") common_meta.to_csv(meta_path, index=False) print(f"筛选后的元数据已保存至: {meta_path}") ``` ### 代码优化说明 #### 1. 新增 `save_common_patients` 函数 ```python def save_common_patients(expr_data, meta_data, patient_id_col, output_dir): # 提取表达数据中的病人ID集合 _, expr_patients = map_sample_to_patient_id(expr_data.columns) expr_patient_set = set(expr_patients) # 提取元数据中的病人ID集合 meta_patient_set = set(meta_data[patient_id_col]) # 计算交集并排序 common_patients = sorted(expr_patient_set & meta_patient_set) # 双重格式保存 pd.DataFrame(common_patients).to_csv("common_patients.csv") # CSV格式 with open("common_patients.txt", 'w') as f: # 文本格式 f.write("\n".join(common_patients)) ``` #### 2. 改进的对齐流程 ```python def align_and_save_patient_data(expr_data, meta_data, ...): # ... [处理表达数据] ... # 保存共同病人ID common_patients, _ = save_common_patients(...) # 筛选共同病人的表达数据 common_expr = patient_expr[list(set(patient_expr.columns) & set(common_patients))] # 按元数据顺序对齐 aligned_expr = common_expr.reindex(columns=common_patients) ``` #### 3. 完整的诊断报告 ```python diagnostic_info = { "meta_count": len(meta_patient_set), "expr_count": len(expr_patient_set), "common_count": len(common_patients), "coverage": len(common_patients)/len(meta_patient_set) } print(f"共同覆盖率: {diagnostic_info['coverage']:.2%}") ``` ### 关键改进点 1. **精确的共同病人ID提取** - 使用集合操作高效计算交集 - 保存多种格式(CSV和文本)便于不同场景使用 2. **完整的数据对齐流程** - 样本ID映射 → 病人ID标准化 - 病人表达数据聚合(平均值) - 共同病人筛选 - 按元数据顺序排列 3. **全面的诊断报告** - 元数据病人总数 - 表达数据病人总数 - 共同病人数量 - 覆盖率百分比 - 保存路径信息 4. **结果文件组织** - 创建专用输出目录 - 命名清晰的输出文件: - `common_patients.csv` - 共同病人ID列表 - `aligned_gene_expression.csv` - 对齐后的表达数据 - `common_patient_metadata.csv` - 筛选后的元数据 ### 使用场景示例 ```python # 加载数据 expr_data = pd.read_csv("gene_expression.csv", index_col=0) meta_data = pd.read_csv("patient_metadata.csv") # 获取共同病人ID common_ids, diag = save_common_patients(expr_data, meta_data, "PATIENT_ID", "results") # 使用共同病人ID筛选数据 common_expr = expr_data[[sid for sid in expr_data.columns if f"aml_ohsu_2018_{int(sid.split('-')[1])}" in common_ids]] common_meta = meta_data[meta_data['PATIENT_ID'].isin(common_ids)] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值