簡體   English   中英

合並兩個數據幀列,列表按列表順序排列

[英]Merged two dataframe columns with lists in order of lists

我正在嘗試合並/連接兩個列相關的列,但是用“|”分隔的單獨文本數據 除了用“”替換某些名稱並替換| 用'\\ n'。

例如,原始數據可能是:

    First Names            Last Names
0   Jim|James|Tim          Simth|Jacobs|Turner
1   Mickey|Mini            Mouse|Mouse
2   Mike|Billy|Natasha     Mills|McGill|Tsaka

如果我想合並/連接以獲取全名並刪除與“Smith”綁定的條目,則最終的df應如下所示:

    First Names            Last Names            Full Names
0   Jim|James|Tim          Simth|Jacobs|Turner   James Jacobs\nTim Turner
1   Mickey|Mini            Mouse|Mouse           Mickey Mouse\nMini Mouse
2   Mike|Billy|Natasha     Mills|McGill|Tsaka    Mike Mills\nBilly McGill\nNatasha Tsaka

到目前為止我目前的做法是:

def parse_merge(df, col1, col2, splitter, new_col, list_to_exclude):

    orig_order = pd.Series(list(df.index)).rename('index')

    col1_df = pd.concat([orig_order, df[col1], df[col1].str.split(splitter, expand=True)], axis = 1)
    col2_df = pd.concat([orig_order, df[col2], df[col2].str.split(splitter, expand=True)], axis = 1)

    col1_melt = pd.melt(col1_df, id_vars=['index', col1], var_name='count')
    col2_melt = pd.melt(col2_df, id_vars=['index', col2], var_name='count')

    col2_melt['value'] = '(' + col2_melt['value'].astype(str) + ')'
    col2_melt = col2_melt.rename(columns={'value':'value2'})

    melted_merge = pd.concat([col1_melt, col2_melt['value2']], axis = 1 )

    if len(list_to_exclude) > 0:
         list_map = map(re.escape, list_to_exclude)

    melted_merge.ix[melted_merge['value2'].str.contains('|'.join(list_map)), ['value', 'value2']] = ''

    melted_merge[new_col] = melted_merge['value'] + " " + melted_merge['value2']

如果我打電話:

parse_merge(names, 'First Names', 'Last Names', 'Full Names', ['Smith'])

數據變為:

    Index   First Names        count    value            value2        Full Names
0   0       Jim|James|Tim      0        Jim              Smith         ''
1   1       Mickey|Mini        0        Mickey           Mouse         Mickey Mouse
2   2       Mike|Billy|Natasha 0        Mike             Mills         Mike Mills

只是不確定如何在沒有任何循環的情況下完成此操作,或者是否有更有效/完全不同的方法。

感謝所有的投入!

這是一個使用pd.DataFrame.apply和python的一些很好的內置功能的精簡解決方案:

def combine_names(row):

    pairs = list(zip(row[0].split('|'), row[1].split('|')))
    return '\n'.join([' '.join(p) for p in pairs if p[1] != 'Simth'])

df['Full Name'] = df.apply(combine_names, axis=1)

我非常喜歡@AlexG的解決方案 - 請使用它。

這是我嘗試創建一個創造性的單行解決方案 - 它絕對有悖常理,所以不應該使用它 - 它只是為了好玩:

In [78]: df
Out[78]:
          First Names           Last Names
0       Jim|James|Tim  Simth|Jacobs|Turner
1         Mickey|Mini          Mouse|Mouse
2  Mike|Billy|Natasha   Mills|McGill|Tsaka

In [79]: df['Full Names'] = \
    ...: (df.stack()
    ...:    .str.split(r'\|', expand=True)
    ...:    .unstack(level=1)
    ...:    .groupby(level=0, axis=1)
    ...:    .apply(lambda x: x.add(' ').sum(axis=1).str.strip())
    ...:    .replace([r'\w+\s+Simth'], [np.nan], regex=True)
    ...:    .apply(lambda x: x.dropna().str.cat(sep='\n'), axis=1)
    ...: )
    ...:

In [80]: df
Out[80]:
          First Names           Last Names                               Full Names
0       Jim|James|Tim  Simth|Jacobs|Turner                 James Jacobs\nTim Turner
1         Mickey|Mini          Mouse|Mouse                 Mickey Mouse\nMini Mouse
2  Mike|Billy|Natasha   Mills|McGill|Tsaka  Mike Mills\nBilly McGill\nNatasha Tsaka

我有很多理解力

l = df.values.tolist()

['|'.join(n)
 for n in [[' '.join(z)
 for z in zip(*[s.split('|')
 for s in r]) if z[1] != 'Smith']
 for r in l]]

['James Jacobs|Tim Turner',
 'Mickey Mouse|Mini Mouse',
 'Mike Mills|Billy McGill|Natasha Tsaka']

l = df.values.tolist()

df['Full Names'] = [
     '|'.join(n)
     for n in [[' '.join(z)
     for z in zip(*[s.split('|')
     for s in r]) if z[1] != 'Smith']
     for r in l]]

df

在此輸入圖像描述


除了文字游戲,這對樣本數據非常敏感

在此輸入圖像描述


更長的解釋

l

[['Jim|James|Tim', 'Simth|Jacobs|Turner'],
 ['Mickey|Mini', 'Mouse|Mouse'],
 ['Mike|Billy|Natasha', 'Mills|McGill|Tsaka']]
  • l是列表清單。 我將廣泛使用列表推導和迭代。
  • 每個子列表由2個字符串組成,我將拆分並壓縮在一起。
  • 拆分的結果將是由(first, last)名稱組成的元組的“列表”。 我會用if z[1] != 'Smith'過濾出史密斯。
    • 順便說一句,在這一行你可以使用z[1] not in list_of_names
  • 然后我會使用' '.join (實際上是一個函數)將每個元組組合到first last一個元組
  • 然后我將使用另一個'|'.joinfirst last的子列表與first1 last1|first2 last2 ...等等結合起來等等

這更快的原因是因為理解已在很大程度上得到優化。 其他解決方案正在使用apply ,這是一種通用的循環結構,只能在特殊情況下利用快速循環(有人知道更多,如果我錯了請糾正我)。 使用lambda絕對不是那種情況之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM