用 1 替换各个列中的多个不同字符串,并用 pandas 中的计数改变一个新列

Replacing multiple different strings in various columns with 1 and mutating a new column with counts in pandas

我用 在 R 中做了这个,但切换到 Python 仍然没有看到好的答案。

我有一个包含 200 列不同字符串和数字的数据框。

示例:

Name  Gender Disease1 Disease2 Disease3
Joe   Male   disease1 NA       disease3
Ben   Male   NA       disease2 NA
Chloe Female disease1 disease2 NA

如何将多个列中的不同 Disease 值转换为 1,然后改变一个新列,计算特定列(可能在列 22:65 中)1 的总数。

期望的输出

Name  Gender Disease1 Disease2 Disease3 Total_diseases
Joe   Male   disease1 NA       disease3 2
Ben   Male   NA       disease2 NA       1
Chloe Female disease1 disease2 NA       2

我想要一个新列 Total_diseases,其中汇总了所有文本值(现已转换为 1)。所以如果一个人有 10 种疾病,它就会出现在这个变异的列中。希望它能回答你的问题。

如果您只想要“Total_diseases”列,则无需对原始列进行任何更改:

df = df.set_index('id')
df['Total_diseases'] = df.nunique(axis=1)

如果最初有 'Disease' 以外的列:

cols = df.filter(like='Disease').columns
df['Total_diseases'] = df[cols].nunique(axis=1)

这只是为了将原始列更改为非 NA 值的一列:

cols = df.filter(like='Disease').columns
df[cols] = df[cols].where(df[cols].isna(), 1)

输出:

   Disease1 Disease2 Disease3  Total_diseases
id                                           
1         1      NaN        1               2
2       NaN        1      NaN               1
3         1        1      NaN               2

您可以在 id 上设置索引,然后使用 notna() 使这些条目不为空,并使用 .astype(int) 将它们更改为 1。然后在 axis=1 上按 .filter()sum 过滤 Disease* 列以计算每行的计数:

df_out = df.set_index('id').notna().astype(int).reset_index()

df_out['Total_diseases'] = df_out.filter(like='Disease').sum(axis=1)

结果

print(df_out)

   id  Disease1  Disease2  Disease3  Total_diseases
0   1         1         0         1               2
1   2         0         1         0               1
2   3         1         1         0               2

编辑:

如果你想通过数字指定列的范围,你可以使用 .iloc 例如使用 df_out.iloc[:, 10:30] 并使用 df_out.iloc[:, 10:30].sum(axis=1) 对这些列求和。

编辑 2

根据更新的样本输入和期望的输出,你提到你想通过列号引用列的范围,而不是像上面的解决方案那样通过过滤类似的列标签(可能真正的疾病名称没有共同点pattern),可以使用.iloc代替,如下:

df['Total_diseases'] = df.iloc[:, 2:5].notna().sum(axis=1)

结果

print(df)

    Name  Gender  Disease1  Disease2  Disease3  Total_diseases
0    Joe    Male  disease1       NaN  disease3               2
1    Ben    Male       NaN  disease2       NaN               1
2  Chloe  Female  disease1  disease2       NaN               2