通过使用Python折叠和创建新列来重塑数据帧的形状



我有一个数据帧,看起来像这样:

data = {'case_id': ['aaa', 'aaa', 'bbb', 'ccc', 'bbb', 'ccc'],
'file_name': ['512.mirnas', '512.isoforms', '360.isoforms', '478.mirnas', '360.mirnas', '478.isoforms']
}
df = pd.DataFrame(data, columns=['case_id', 'file_name'])
case_id     file_name
0     aaa    512.mirnas
1     aaa  512.isoforms
2     bbb  360.isoforms
3     ccc    478.mirnas
4     bbb    360.mirnas
5     ccc  478.isoforms

对于每个唯一的";case_ id";,存在两个";文件名称";,一个mirnas和一个异构体。我想把";case_id";并为mirnas和isoforms文件名创建新列。我正在努力实现这一点:

case_id file_name_mirnas file_name_isoforms
0     aaa       512.mirnas       512.isoforms
1     bbb       360.mirnas       360.isoforms
2     ccc       478.mirnas       478.isoforms

我是Python的新手,我发现很难完成这项工作。我试了一下df.pivot,但没用。我得到以下错误:ValueError: Index contains duplicate entries, cannot reshape

我在想也许我可以创建两个新的空列";file_name_mirnas";以及";file_name_isoforms";,然后使用groupby填充这些列。但我不太确定该怎么做。

有人能帮忙吗?

您可以将它们分离成不同的数据帧,然后将它们连接在一起:

我还注意到,一些值被称为";mirna";而不是";mirnas";。我把这个改成了我的答案。

import pandas as pd
data = {'case_id': ['aaa', 'aaa', 'bbb', 'ccc', 'bbb', 'ccc'],
'file_name': ['512.mirnas', '512.isoforms', '360.isoforms', '478.mirnas', '360.mirnas', '478.isoforms']
}
df = pd.DataFrame(data, columns=['case_id', 'file_name'])
df_mirnas = df[df["file_name"].str.endswith("mirnas")]  # Grabs all that end with mirnas
df_mirnas.rename(columns={"file_name": "file_name_mirnas"}, inplace=True)  # Rename for join
df_iso = df[df["file_name"].str.endswith("isoforms")]  # Grabs all that ends with isoforms
df_iso.rename(columns={"file_name": "file_name_isoforms"}, inplace=True)  # rename for join
df_new = df_mirnas.join(df_iso.set_index("case_id"), on="case_id") # Joins them on case_id
df_new
>> 
case_id file_name_mirnas    file_name_isoforms
0   aaa 512.mirnas  512.isoforms
3   ccc 478.mirnas  478.isoforms
4   bbb 360.mirnas  360.isoforms

PS,我认为groupby使用起来非常不直观,所以不要因为不总是使用它而感到难过(即使它可能更高效,就像这里一样(

如果你不知道panda中的查询,那么你可以这样做。1-分隔行2-为每个案例选择两个文件名3-制作新的数据帧


from numpy.lib.arraysetops import unique
import pandas as pd
data = {'case_id': ['aaa', 'aaa', 'bbb', 'ccc', 'bbb', 'ccc'],
'file_name': ['512.mirnas', '512.isoforms', '360.isoforms', '478.mirnas', '360.mirnas', '478.isoforms']
}
df = pd.DataFrame(data, columns=['case_id', 'file_name'])
print(df)
unique_caseid = sorted(set(df.loc[:, 'case_id']))
mirnas = []
isoforms = []
for id in unique_caseid:
# first file name
temp_index = list(df.loc[:, 'case_id']).index(id)
file_name = df.loc[temp_index, 'file_name']
if 'mirnas' in file_name:
mirnas.append(file_name)
else:
isoforms.append(file_name)
# 2nd file name
ntemp_index = list(df.loc[:, 'case_id'])[temp_index+1:].index(id)
temp_index += ntemp_index+1
file_name = df.loc[temp_index, 'file_name']
if 'mirnas' in file_name:
mirnas.append(file_name)
else:
isoforms.append(file_name)
data = {}
data['case_id'] = unique_caseid
data['file_name_mirnas'] = mirnas
data['file_name_iosforms'] = isoforms
newdf = pd.DataFrame(
data, columns=['case_id', 'file_name_mirnas', 'file_name_iosforms'])
print(newdf)

您可以创建一个临时列来容纳mirnasisoforms,然后使用pivot函数来重塑数据,最后使用列表理解来折叠列:

df = (df.assign(temp=df.file_name.str.split(".").str[-1])
.pivot("case_id", "temp")
)
# flatten columns
df.columns = ["_".join(entry) for entry in df]
df.reset_index()
case_id  file_name_isoforms  file_name_mirnas
0   aaa     512.isoforms        512.mirnas
1   bbb     360.isoforms        360.mirnas
2   ccc     478.isoforms        478.mirnas

最新更新